Re: [PATCH v2] ARM: dts: add reset property for rk3066a-rayeager emac phy

2017-12-17 Thread Chris Zhong

Hi Heiko

Thanks :)


On 2017??12??17?? 04:11, Heiko Stuebner wrote:

Hi Chris,

Am Mittwoch, 8. November 2017, 17:50:41 CET schrieb Chris Zhong:

The ethernet phy of rk3066a-rayeager has a reset pin, it controlled by
GPIO1_D6, this pin should be pull down then pull up to reset the phy.
Add a reset-gpios property in phy0, make the phy can be reset when emac
power on.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v2:
use a generic property for reset, and this patch follow these 2 pathes
from Geert Uytterhoeven <geert+rene...@glider.be>
http://patchwork.ozlabs.org/patch/828499/
http://patchwork.ozlabs.org/patch/828505/

looks like the phylib-patches were accepted some days ago,
so I've now also applied this patch for 4.16, after fixing the subject
by adding the "rockchip:" to "ARM: dts: rockchip": :-)


Heiko





--
Chris Zhong




Re: [PATCH v2] ARM: dts: add reset property for rk3066a-rayeager emac phy

2017-12-17 Thread Chris Zhong

Hi Heiko

Thanks :)


On 2017??12??17?? 04:11, Heiko Stuebner wrote:

Hi Chris,

Am Mittwoch, 8. November 2017, 17:50:41 CET schrieb Chris Zhong:

The ethernet phy of rk3066a-rayeager has a reset pin, it controlled by
GPIO1_D6, this pin should be pull down then pull up to reset the phy.
Add a reset-gpios property in phy0, make the phy can be reset when emac
power on.

Signed-off-by: Chris Zhong 
---

Changes in v2:
use a generic property for reset, and this patch follow these 2 pathes
from Geert Uytterhoeven 
http://patchwork.ozlabs.org/patch/828499/
http://patchwork.ozlabs.org/patch/828505/

looks like the phylib-patches were accepted some days ago,
so I've now also applied this patch for 4.16, after fixing the subject
by adding the "rockchip:" to "ARM: dts: rockchip": :-)


Heiko





--
Chris Zhong




Re: [PATCH 0/4] Move DP phy switch to PHY driver

2017-12-03 Thread Chris Zhong

Hi Heiko


On 2017??12??02?? 05:58, Heiko Stuebner wrote:

Am Freitag, 1. Dezember 2017, 13:42:46 CET schrieb Doug Anderson:

Hi,

On Wed, Nov 29, 2017 at 6:27 PM, Chris Zhong <z...@rock-chips.com> wrote:

Hi Doug

Thank you for mentioning this patch.

I think the focus of the discussion is: can we put the grf control bit to
dts.

The RK3399 has 2 Type-C phy, but only one DP controller, this "uphy_dp_sel"

can help to switch these 2 phy. So I think this bit can be considered as a
part of

Type-C phy, these 2 phy have different bits, just similar to other bits
(such as "pipe-status").

Put them to DTS file might be a accepted practice.

I guess the first step would be finding the person to make a decision.
Is that Heiko?  Olof?  Kishon?  Rob?.  As I see it there are a few
options:

1. Land this series as-is.  This makes the new bit work just like all
the other ones next to it.  If anyone happens to try to use an old
device tree on a new kernel they'll break.  Seems rather unlikely
given that the whole type C PHY is not really fully functional
upstream, but technically this is a no-no from a device tree
perspective.

2. Change the series to make this property optional.  If it's not
there then the code behaves like it always did.  This would address
the "compatibility" problem but likely wouldn't actually help any real
people, and it would be extra work.

3. Redo the driver to deprecate all the old offsets / bits and just
put the table in the driver, keyed off the compatible string and base
address if the IO memory.


I can't make this decision.  It's up to those folks who would be
landing the patch and I'd be happy with any of them.  What I'm less
happy with, however, is the indecision preventing forward progress.
We should pick one of the above things and land it.  My own personal
bias is #1: just land the series.  No real people will be hurt and
it's just adding another property that matches the ones next to it.

I'd second that #1 . That whole type-c phy thingy never fully worked in
the past (some for the never used dp output), so personally I don't have
issues with going that route.



 From a long term perspective (AKA how I'd write the next driver like
this) I personally lean towards to "tables in the driver, not in the
device tree" but quite honestly I'm happy to take whatever direction
the maintainers give.

It looks like we're in agreement here :-) . GRF stuff should not leak into
the devicetree, as it causes endless headaches later. But I guess we'll
need to live with the ones that happened so far.

So, the first step is: move all the private property of tcphy to 
drivers/phy/rockchip/phy-rockchip-typec.c.

Second step: new a member: uphy-dp-sel.
In my mind, we should have discussed these properties before, and then I 
moved them all into DTS.










--
Chris Zhong




Re: [PATCH 0/4] Move DP phy switch to PHY driver

2017-12-03 Thread Chris Zhong

Hi Heiko


On 2017??12??02?? 05:58, Heiko Stuebner wrote:

Am Freitag, 1. Dezember 2017, 13:42:46 CET schrieb Doug Anderson:

Hi,

On Wed, Nov 29, 2017 at 6:27 PM, Chris Zhong  wrote:

Hi Doug

Thank you for mentioning this patch.

I think the focus of the discussion is: can we put the grf control bit to
dts.

The RK3399 has 2 Type-C phy, but only one DP controller, this "uphy_dp_sel"

can help to switch these 2 phy. So I think this bit can be considered as a
part of

Type-C phy, these 2 phy have different bits, just similar to other bits
(such as "pipe-status").

Put them to DTS file might be a accepted practice.

I guess the first step would be finding the person to make a decision.
Is that Heiko?  Olof?  Kishon?  Rob?.  As I see it there are a few
options:

1. Land this series as-is.  This makes the new bit work just like all
the other ones next to it.  If anyone happens to try to use an old
device tree on a new kernel they'll break.  Seems rather unlikely
given that the whole type C PHY is not really fully functional
upstream, but technically this is a no-no from a device tree
perspective.

2. Change the series to make this property optional.  If it's not
there then the code behaves like it always did.  This would address
the "compatibility" problem but likely wouldn't actually help any real
people, and it would be extra work.

3. Redo the driver to deprecate all the old offsets / bits and just
put the table in the driver, keyed off the compatible string and base
address if the IO memory.


I can't make this decision.  It's up to those folks who would be
landing the patch and I'd be happy with any of them.  What I'm less
happy with, however, is the indecision preventing forward progress.
We should pick one of the above things and land it.  My own personal
bias is #1: just land the series.  No real people will be hurt and
it's just adding another property that matches the ones next to it.

I'd second that #1 . That whole type-c phy thingy never fully worked in
the past (some for the never used dp output), so personally I don't have
issues with going that route.



 From a long term perspective (AKA how I'd write the next driver like
this) I personally lean towards to "tables in the driver, not in the
device tree" but quite honestly I'm happy to take whatever direction
the maintainers give.

It looks like we're in agreement here :-) . GRF stuff should not leak into
the devicetree, as it causes endless headaches later. But I guess we'll
need to live with the ones that happened so far.

So, the first step is: move all the private property of tcphy to 
drivers/phy/rockchip/phy-rockchip-typec.c.

Second step: new a member: uphy-dp-sel.
In my mind, we should have discussed these properties before, and then I 
moved them all into DTS.










--
Chris Zhong




Re: [PATCH 0/4] Move DP phy switch to PHY driver

2017-11-29 Thread Chris Zhong

Hi Doug

Thank you for mentioning this patch.

I think the focus of the discussion is: can we put the grf control bit 
to dts.


The RK3399 has 2 Type-C phy, but only one DP controller, this "uphy_dp_sel"

can help to switch these 2 phy. So I think this bit can be considered as 
a part of


Type-C phy, these 2 phy have different bits, just similar to other bits 
(such as "pipe-status").


Put them to DTS file might be a accepted practice.



On 2017年11月29日 07:32, Doug Anderson wrote:

Hi,

On Thu, Feb 9, 2017 at 11:44 PM, Chris Zhong <z...@rock-chips.com> wrote:

There are 2 Type-c PHYs in RK3399, but only one DP controller. Hence
only one PHY can connect to DP controller at one time, the other should
be disconnected. The GRF_SOC_CON26 register has a switch bit to do it,
set this bit means enable PHY 1, clear this bit means enable PHY 0.

If the board has 2 Type-C ports, the DP driver get the phy id from
devm_of_phy_get_by_index, and then control this switch according to
this id. But some others board only has one Type-C port, it may be PHY 0
or PHY 1. The dts node id can not tell us the correct PHY id. Hence move
this switch to PHY driver, the PHY driver can distinguish between PHY 0
and PHY 1, and then write the correct register bit.



Chris Zhong (4):
   Documentation: bindings: add uphy-dp-sel for Rockchip USB Type-C PHY
   arm64: dts: rockchip: add rockchip,uphy-dp-sel for Type-C phy
   phy: rockchip-typec: support DP phy switch
   drm/rockchip: cdn-dp: remove the DP phy switch

  Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt | 5 +
  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 ++
  drivers/gpu/drm/rockchip/cdn-dp-core.c   | 7 ---
  drivers/phy/phy-rockchip-typec.c | 9 +
  4 files changed, 16 insertions(+), 7 deletions(-)

What ever happened to this series?  It seemed like it just dropped on
the floor...

There was a bit of contention on patch #3
<https://patchwork.kernel.org/patch/9566095/> about the fact that we
were specifying addresses in the device tree vs. hardcoding them in
the driver.  Any way we can just make a decision and go with it?


-Doug





--
Chris Zhong




Re: [PATCH 0/4] Move DP phy switch to PHY driver

2017-11-29 Thread Chris Zhong

Hi Doug

Thank you for mentioning this patch.

I think the focus of the discussion is: can we put the grf control bit 
to dts.


The RK3399 has 2 Type-C phy, but only one DP controller, this "uphy_dp_sel"

can help to switch these 2 phy. So I think this bit can be considered as 
a part of


Type-C phy, these 2 phy have different bits, just similar to other bits 
(such as "pipe-status").


Put them to DTS file might be a accepted practice.



On 2017年11月29日 07:32, Doug Anderson wrote:

Hi,

On Thu, Feb 9, 2017 at 11:44 PM, Chris Zhong  wrote:

There are 2 Type-c PHYs in RK3399, but only one DP controller. Hence
only one PHY can connect to DP controller at one time, the other should
be disconnected. The GRF_SOC_CON26 register has a switch bit to do it,
set this bit means enable PHY 1, clear this bit means enable PHY 0.

If the board has 2 Type-C ports, the DP driver get the phy id from
devm_of_phy_get_by_index, and then control this switch according to
this id. But some others board only has one Type-C port, it may be PHY 0
or PHY 1. The dts node id can not tell us the correct PHY id. Hence move
this switch to PHY driver, the PHY driver can distinguish between PHY 0
and PHY 1, and then write the correct register bit.



Chris Zhong (4):
   Documentation: bindings: add uphy-dp-sel for Rockchip USB Type-C PHY
   arm64: dts: rockchip: add rockchip,uphy-dp-sel for Type-C phy
   phy: rockchip-typec: support DP phy switch
   drm/rockchip: cdn-dp: remove the DP phy switch

  Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt | 5 +
  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 ++
  drivers/gpu/drm/rockchip/cdn-dp-core.c   | 7 ---
  drivers/phy/phy-rockchip-typec.c | 9 +
  4 files changed, 16 insertions(+), 7 deletions(-)

What ever happened to this series?  It seemed like it just dropped on
the floor...

There was a bit of contention on patch #3
<https://patchwork.kernel.org/patch/9566095/> about the fact that we
were specifying addresses in the device tree vs. hardcoding them in
the driver.  Any way we can just make a decision and go with it?


-Doug





--
Chris Zhong




Re: [PATCH] ARM: dts: add phy-reset property for rk3066a-rayeager emac

2017-11-08 Thread Chris Zhong

Hi Florian Fainelli


On 2017年11月08日 02:26, Florian Fainelli wrote:

On 11/07/2017 01:51 AM, Chris Zhong wrote:


On 2017年11月07日 15:54, Vladimir Zapolskiy wrote:

Hello Chris,

On 11/07/2017 04:49 AM, Chris Zhong wrote:

The ethernet phy of rk3066a-rayeager has a reset pin, it controlled by
GPIO1_D6, this pin should be pull down then pull up to reset the phy.
Add a phy-reset property in emac, make the phy can be reset when emac
power on.

for PHY reset there are properties 'reset-gpios' and 'reset-delay-us',
please reference to Documentation/devicetree/bindings/net/mdio.txt

Can you try to reuse them instead of adding new custom properties?

This phy-reset is from Documentation/devicetree/bindings/net/arc_emac.txt.
And copy from arch/arm/boot/dts/rk3036-kylin.dts.
Can we just use these properties, they are not new.

Because it already exists does not mean it's correct, in fact, it is not
at all because it places the reset property for a PHY into the MAC node,
which is just not what this is, what we should be using instead is the
following patch series:

http://patchwork.ozlabs.org/project/netdev/list/?series=9267

http://patchwork.ozlabs.org/patch/828499/
http://patchwork.ozlabs.org/patch/828505/
http://patchwork.ozlabs.org/patch/828501/
http://patchwork.ozlabs.org/patch/828502/
Okay, this series works for me, and I will push a new version patch 
following it,

with a reset-gpios property under phy node.
And hope this series can be applied soon.

Thanks
Chris Zhong



As a side question, which is mainly addressed to Sergei and Roger,
I don't quite understand why PHY properties were initially added to
MAC/MDIO bus device tree nodes, in my opinion they must be moved under
PHY device tree nodes.

--
With best wishes,
Vladimir


Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

   arch/arm/boot/dts/rk3066a-rayeager.dts | 2 ++
   1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/rk3066a-rayeager.dts
b/arch/arm/boot/dts/rk3066a-rayeager.dts
index 570157f..6064a0a 100644
--- a/arch/arm/boot/dts/rk3066a-rayeager.dts
+++ b/arch/arm/boot/dts/rk3066a-rayeager.dts
@@ -173,6 +173,8 @@
   pinctrl-0 = <_xfer>, <_mdio>, <_rst>;
   phy = <>;
   phy-supply = <_rmii>;
+phy-reset-gpios = < RK_PD6 GPIO_ACTIVE_LOW>; /* PHY_RST */
+phy-reset-duration = <10>; /* millisecond */
   status = "okay";
 phy0: ethernet-phy@0 {









[PATCH v2] ARM: dts: add reset property for rk3066a-rayeager emac phy

2017-11-08 Thread Chris Zhong
The ethernet phy of rk3066a-rayeager has a reset pin, it controlled by
GPIO1_D6, this pin should be pull down then pull up to reset the phy.
Add a reset-gpios property in phy0, make the phy can be reset when emac
power on.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v2:
use a generic property for reset, and this patch follow these 2 pathes
from Geert Uytterhoeven <geert+rene...@glider.be>
http://patchwork.ozlabs.org/patch/828499/
http://patchwork.ozlabs.org/patch/828505/

 arch/arm/boot/dts/rk3066a-rayeager.dts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/rk3066a-rayeager.dts 
b/arch/arm/boot/dts/rk3066a-rayeager.dts
index 570157f..04c1f97 100644
--- a/arch/arm/boot/dts/rk3066a-rayeager.dts
+++ b/arch/arm/boot/dts/rk3066a-rayeager.dts
@@ -177,6 +177,7 @@
 
phy0: ethernet-phy@0 {
reg = <0>;
+   reset-gpios = < RK_PD6 GPIO_ACTIVE_LOW>;
};
 };
 
-- 
2.7.4



Re: [PATCH] ARM: dts: add phy-reset property for rk3066a-rayeager emac

2017-11-08 Thread Chris Zhong

Hi Florian Fainelli


On 2017年11月08日 02:26, Florian Fainelli wrote:

On 11/07/2017 01:51 AM, Chris Zhong wrote:


On 2017年11月07日 15:54, Vladimir Zapolskiy wrote:

Hello Chris,

On 11/07/2017 04:49 AM, Chris Zhong wrote:

The ethernet phy of rk3066a-rayeager has a reset pin, it controlled by
GPIO1_D6, this pin should be pull down then pull up to reset the phy.
Add a phy-reset property in emac, make the phy can be reset when emac
power on.

for PHY reset there are properties 'reset-gpios' and 'reset-delay-us',
please reference to Documentation/devicetree/bindings/net/mdio.txt

Can you try to reuse them instead of adding new custom properties?

This phy-reset is from Documentation/devicetree/bindings/net/arc_emac.txt.
And copy from arch/arm/boot/dts/rk3036-kylin.dts.
Can we just use these properties, they are not new.

Because it already exists does not mean it's correct, in fact, it is not
at all because it places the reset property for a PHY into the MAC node,
which is just not what this is, what we should be using instead is the
following patch series:

http://patchwork.ozlabs.org/project/netdev/list/?series=9267

http://patchwork.ozlabs.org/patch/828499/
http://patchwork.ozlabs.org/patch/828505/
http://patchwork.ozlabs.org/patch/828501/
http://patchwork.ozlabs.org/patch/828502/
Okay, this series works for me, and I will push a new version patch 
following it,

with a reset-gpios property under phy node.
And hope this series can be applied soon.

Thanks
Chris Zhong



As a side question, which is mainly addressed to Sergei and Roger,
I don't quite understand why PHY properties were initially added to
MAC/MDIO bus device tree nodes, in my opinion they must be moved under
PHY device tree nodes.

--
With best wishes,
Vladimir


Signed-off-by: Chris Zhong 
---

   arch/arm/boot/dts/rk3066a-rayeager.dts | 2 ++
   1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/rk3066a-rayeager.dts
b/arch/arm/boot/dts/rk3066a-rayeager.dts
index 570157f..6064a0a 100644
--- a/arch/arm/boot/dts/rk3066a-rayeager.dts
+++ b/arch/arm/boot/dts/rk3066a-rayeager.dts
@@ -173,6 +173,8 @@
   pinctrl-0 = <_xfer>, <_mdio>, <_rst>;
   phy = <>;
   phy-supply = <_rmii>;
+phy-reset-gpios = < RK_PD6 GPIO_ACTIVE_LOW>; /* PHY_RST */
+phy-reset-duration = <10>; /* millisecond */
   status = "okay";
 phy0: ethernet-phy@0 {









[PATCH v2] ARM: dts: add reset property for rk3066a-rayeager emac phy

2017-11-08 Thread Chris Zhong
The ethernet phy of rk3066a-rayeager has a reset pin, it controlled by
GPIO1_D6, this pin should be pull down then pull up to reset the phy.
Add a reset-gpios property in phy0, make the phy can be reset when emac
power on.

Signed-off-by: Chris Zhong 
---

Changes in v2:
use a generic property for reset, and this patch follow these 2 pathes
from Geert Uytterhoeven 
http://patchwork.ozlabs.org/patch/828499/
http://patchwork.ozlabs.org/patch/828505/

 arch/arm/boot/dts/rk3066a-rayeager.dts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/rk3066a-rayeager.dts 
b/arch/arm/boot/dts/rk3066a-rayeager.dts
index 570157f..04c1f97 100644
--- a/arch/arm/boot/dts/rk3066a-rayeager.dts
+++ b/arch/arm/boot/dts/rk3066a-rayeager.dts
@@ -177,6 +177,7 @@
 
phy0: ethernet-phy@0 {
reg = <0>;
+   reset-gpios = < RK_PD6 GPIO_ACTIVE_LOW>;
};
 };
 
-- 
2.7.4



Re: [PATCH] ARM: dts: add phy-reset property for rk3066a-rayeager emac

2017-11-07 Thread Chris Zhong



On 2017年11月07日 15:54, Vladimir Zapolskiy wrote:

Hello Chris,

On 11/07/2017 04:49 AM, Chris Zhong wrote:

The ethernet phy of rk3066a-rayeager has a reset pin, it controlled by
GPIO1_D6, this pin should be pull down then pull up to reset the phy.
Add a phy-reset property in emac, make the phy can be reset when emac
power on.

for PHY reset there are properties 'reset-gpios' and 'reset-delay-us',
please reference to Documentation/devicetree/bindings/net/mdio.txt

Can you try to reuse them instead of adding new custom properties?

This phy-reset is from Documentation/devicetree/bindings/net/arc_emac.txt.
And copy from arch/arm/boot/dts/rk3036-kylin.dts.
Can we just use these properties, they are not new.

As a side question, which is mainly addressed to Sergei and Roger,
I don't quite understand why PHY properties were initially added to
MAC/MDIO bus device tree nodes, in my opinion they must be moved under
PHY device tree nodes.

--
With best wishes,
Vladimir


Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

  arch/arm/boot/dts/rk3066a-rayeager.dts | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/rk3066a-rayeager.dts 
b/arch/arm/boot/dts/rk3066a-rayeager.dts
index 570157f..6064a0a 100644
--- a/arch/arm/boot/dts/rk3066a-rayeager.dts
+++ b/arch/arm/boot/dts/rk3066a-rayeager.dts
@@ -173,6 +173,8 @@
pinctrl-0 = <_xfer>, <_mdio>, <_rst>;
phy = <>;
phy-supply = <_rmii>;
+   phy-reset-gpios = < RK_PD6 GPIO_ACTIVE_LOW>; /* PHY_RST */
+   phy-reset-duration = <10>; /* millisecond */
status = "okay";
  
  	phy0: ethernet-phy@0 {







--
Chris Zhong




Re: [PATCH] ARM: dts: add phy-reset property for rk3066a-rayeager emac

2017-11-07 Thread Chris Zhong



On 2017年11月07日 15:54, Vladimir Zapolskiy wrote:

Hello Chris,

On 11/07/2017 04:49 AM, Chris Zhong wrote:

The ethernet phy of rk3066a-rayeager has a reset pin, it controlled by
GPIO1_D6, this pin should be pull down then pull up to reset the phy.
Add a phy-reset property in emac, make the phy can be reset when emac
power on.

for PHY reset there are properties 'reset-gpios' and 'reset-delay-us',
please reference to Documentation/devicetree/bindings/net/mdio.txt

Can you try to reuse them instead of adding new custom properties?

This phy-reset is from Documentation/devicetree/bindings/net/arc_emac.txt.
And copy from arch/arm/boot/dts/rk3036-kylin.dts.
Can we just use these properties, they are not new.

As a side question, which is mainly addressed to Sergei and Roger,
I don't quite understand why PHY properties were initially added to
MAC/MDIO bus device tree nodes, in my opinion they must be moved under
PHY device tree nodes.

--
With best wishes,
Vladimir


Signed-off-by: Chris Zhong 
---

  arch/arm/boot/dts/rk3066a-rayeager.dts | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/rk3066a-rayeager.dts 
b/arch/arm/boot/dts/rk3066a-rayeager.dts
index 570157f..6064a0a 100644
--- a/arch/arm/boot/dts/rk3066a-rayeager.dts
+++ b/arch/arm/boot/dts/rk3066a-rayeager.dts
@@ -173,6 +173,8 @@
pinctrl-0 = <_xfer>, <_mdio>, <_rst>;
phy = <>;
phy-supply = <_rmii>;
+   phy-reset-gpios = < RK_PD6 GPIO_ACTIVE_LOW>; /* PHY_RST */
+   phy-reset-duration = <10>; /* millisecond */
status = "okay";
  
  	phy0: ethernet-phy@0 {







--
Chris Zhong




[PATCH] ARM: dts: add phy-reset property for rk3066a-rayeager emac

2017-11-06 Thread Chris Zhong
The ethernet phy of rk3066a-rayeager has a reset pin, it controlled by
GPIO1_D6, this pin should be pull down then pull up to reset the phy.
Add a phy-reset property in emac, make the phy can be reset when emac
power on.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

 arch/arm/boot/dts/rk3066a-rayeager.dts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/rk3066a-rayeager.dts 
b/arch/arm/boot/dts/rk3066a-rayeager.dts
index 570157f..6064a0a 100644
--- a/arch/arm/boot/dts/rk3066a-rayeager.dts
+++ b/arch/arm/boot/dts/rk3066a-rayeager.dts
@@ -173,6 +173,8 @@
pinctrl-0 = <_xfer>, <_mdio>, <_rst>;
phy = <>;
phy-supply = <_rmii>;
+   phy-reset-gpios = < RK_PD6 GPIO_ACTIVE_LOW>; /* PHY_RST */
+   phy-reset-duration = <10>; /* millisecond */
status = "okay";
 
phy0: ethernet-phy@0 {
-- 
2.7.4



[PATCH] ARM: dts: add phy-reset property for rk3066a-rayeager emac

2017-11-06 Thread Chris Zhong
The ethernet phy of rk3066a-rayeager has a reset pin, it controlled by
GPIO1_D6, this pin should be pull down then pull up to reset the phy.
Add a phy-reset property in emac, make the phy can be reset when emac
power on.

Signed-off-by: Chris Zhong 
---

 arch/arm/boot/dts/rk3066a-rayeager.dts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/rk3066a-rayeager.dts 
b/arch/arm/boot/dts/rk3066a-rayeager.dts
index 570157f..6064a0a 100644
--- a/arch/arm/boot/dts/rk3066a-rayeager.dts
+++ b/arch/arm/boot/dts/rk3066a-rayeager.dts
@@ -173,6 +173,8 @@
pinctrl-0 = <_xfer>, <_mdio>, <_rst>;
phy = <>;
phy-supply = <_rmii>;
+   phy-reset-gpios = < RK_PD6 GPIO_ACTIVE_LOW>; /* PHY_RST */
+   phy-reset-duration = <10>; /* millisecond */
status = "okay";
 
phy0: ethernet-phy@0 {
-- 
2.7.4



Re: [PATCH] ARM: Fix zImage file size not aligned with CONFIG_EFI_STUB enabled

2017-10-18 Thread Chris Zhong

Tested-by: Chris Zhong <z...@rock-chips.com>


On Wednesday, October 18, 2017 01:01 PM, Jeffy Chen wrote:

The zImage file size should be aligned.

Fixes: e4bae4d0b5f3 ("arm/efi: Split zImage code and data into separate PE/COFF 
sections")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

  arch/arm/boot/compressed/vmlinux.lds.S | 8 
  1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/compressed/vmlinux.lds.S 
b/arch/arm/boot/compressed/vmlinux.lds.S
index b38dcef90756..1636fa259577 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.S
+++ b/arch/arm/boot/compressed/vmlinux.lds.S
@@ -70,10 +70,6 @@ SECTIONS
.got: { *(.got) }
_got_end = .;
  
-  /* ensure the zImage file size is always a multiple of 64 bits */

-  /* (without a dummy byte, ld just ignores the empty section) */
-  .pad : { BYTE(0); . = ALIGN(8); }
-
  #ifdef CONFIG_EFI_STUB
.data : ALIGN(4096) {
  __pecoff_data_start = .;
@@ -93,6 +89,10 @@ SECTIONS
__pecoff_data_rawsize = . - ADDR(.data);
  #endif
  
+  /* ensure the zImage file size is always a multiple of 64 bits */

+  /* (without a dummy byte, ld just ignores the empty section) */
+  .pad : { BYTE(0); . = ALIGN(8); }
+
_edata = .;
  
_magic_sig = ZIMAGE_MAGIC(0x016f2818);


--
Chris Zhong




Re: [PATCH] ARM: Fix zImage file size not aligned with CONFIG_EFI_STUB enabled

2017-10-18 Thread Chris Zhong

Tested-by: Chris Zhong 


On Wednesday, October 18, 2017 01:01 PM, Jeffy Chen wrote:

The zImage file size should be aligned.

Fixes: e4bae4d0b5f3 ("arm/efi: Split zImage code and data into separate PE/COFF 
sections")
Signed-off-by: Jeffy Chen 
---

  arch/arm/boot/compressed/vmlinux.lds.S | 8 
  1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/compressed/vmlinux.lds.S 
b/arch/arm/boot/compressed/vmlinux.lds.S
index b38dcef90756..1636fa259577 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.S
+++ b/arch/arm/boot/compressed/vmlinux.lds.S
@@ -70,10 +70,6 @@ SECTIONS
.got: { *(.got) }
_got_end = .;
  
-  /* ensure the zImage file size is always a multiple of 64 bits */

-  /* (without a dummy byte, ld just ignores the empty section) */
-  .pad : { BYTE(0); . = ALIGN(8); }
-
  #ifdef CONFIG_EFI_STUB
.data : ALIGN(4096) {
  __pecoff_data_start = .;
@@ -93,6 +89,10 @@ SECTIONS
__pecoff_data_rawsize = . - ADDR(.data);
  #endif
  
+  /* ensure the zImage file size is always a multiple of 64 bits */

+  /* (without a dummy byte, ld just ignores the empty section) */
+  .pad : { BYTE(0); . = ALIGN(8); }
+
_edata = .;
  
_magic_sig = ZIMAGE_MAGIC(0x016f2818);


--
Chris Zhong




[PATCH v3 2/2] drm/rockchip: cdn-dp: send audio infoframe to sink

2017-07-26 Thread Chris Zhong
Some DP/HDMI sink need to receive the audio infoframe to play sound,
especially some multi-channel AV receiver, they need the
channel_allocation from infoframe to config the speakers. Send the
audio infoframe via SDP will make them work properly.

Signed-off-by: Chris Zhong <z...@rock-chips.com>

---

Changes in v3: None
Changes in v2:
- According to the advice of Sean Paul and Doug
use hdmi_audio_infoframe_pack_payload to pack the buffer
define a SDP_HEADER_SIZE

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 20 
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 27 +++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  |  6 ++
 include/drm/drm_dp_helper.h|  1 +
 4 files changed, 54 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 9b0b058..6a4fc66 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -802,6 +802,7 @@ static int cdn_dp_audio_hw_params(struct device *dev,  void 
*data,
.sample_rate = params->sample_rate,
.channels = params->channels,
};
+   u8 buffer[HDMI_AUDIO_INFOFRAME_SIZE + EDP_SDP_HEADER_SIZE] = { 0 };
int ret;
 
mutex_lock(>lock);
@@ -823,6 +824,25 @@ static int cdn_dp_audio_hw_params(struct device *dev,  
void *data,
goto out;
}
 
+   /*
+* Prepare the infoframe header to SDP header per DP 1.3 spec, Table
+* 2-98.
+*/
+   buffer[0] = 0;
+   buffer[1] = HDMI_INFOFRAME_TYPE_AUDIO;
+   buffer[2] = 0x1b;
+   buffer[3] = 0x48;
+
+   ret = hdmi_audio_infoframe_pack_payload(>cea,
+   [EDP_SDP_HEADER_SIZE],
+   HDMI_AUDIO_INFOFRAME_SIZE);
+   if (ret < 0) {
+   DRM_DEV_ERROR(dev, "Failed to pack audio infoframe: %d\n", ret);
+   goto out;
+   }
+
+   cdn_dp_sdp_write(dp, 0, buffer, sizeof(buffer));
+
ret = cdn_dp_audio_config(dp, );
if (!ret)
dp->audio_info = audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index b14d211..4a818e4 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -286,6 +286,33 @@ int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, 
u8 value)
return ret;
 }
 
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf,
+ u32 buf_len)
+{
+   int idx;
+   u32 *packet = (u32 *)buf;
+   u32 num_packets = buf_len / 4;
+   u8 type;
+
+   if (buf_len < EDP_SDP_HEADER_SIZE) {
+   DRM_DEV_ERROR(dp->dev, "sdp buffer length: %d\n", buf_len);
+   return;
+   }
+
+   type = buf[1];
+
+   for (idx = 0; idx < num_packets; idx++)
+   writel(cpu_to_le32(*packet++), dp->regs + SOURCE_PIF_DATA_WR);
+
+   writel(entry_id, dp->regs + SOURCE_PIF_WR_ADDR);
+
+   writel(F_HOST_WR, dp->regs + SOURCE_PIF_WR_REQ);
+
+   writel(PIF_PKT_TYPE_VALID | F_PACKET_TYPE(type) | entry_id,
+  dp->regs + SOURCE_PIF_PKT_ALLOC_REG);
+   writel(PIF_PKT_ALLOC_WR_EN, dp->regs + SOURCE_PIF_PKT_ALLOC_WR_EN);
+}
+
 int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem,
 u32 i_size, const u32 *d_mem, u32 d_size)
 {
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index c4bbb4a83..6ec0e81 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -424,6 +424,11 @@
 /* Reference cycles when using lane clock as reference */
 #define LANE_REF_CYC   0x8000
 
+#define F_HOST_WR  BIT(0)
+#define PIF_PKT_ALLOC_WR_ENBIT(0)
+#define PIF_PKT_TYPE_VALID (3 << 16)
+#define F_PACKET_TYPE(x)   (((x) & 0xff) << 8)
+
 enum voltage_swing_level {
VOLTAGE_LEVEL_0,
VOLTAGE_LEVEL_1,
@@ -478,5 +483,6 @@ int cdn_dp_set_video_status(struct cdn_dp_device *dp, int 
active);
 int cdn_dp_config_video(struct cdn_dp_device *dp);
 int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio);
 int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable);
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf, u32 
len);
 int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio);
 #endif /* _CDN_DP_REG_H */
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index b17476a..5d5dd07 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -878,6 +878,7 @@ struct edp_sdp_header {
u8 HB3; /* 7:5 reserved, 4:0 number of valid data bytes */
 } __packed;
 
+#define EDP_SDP_HEADER_SIZE4
 #define EDP_SDP_HEADER_REVISION_MASK   0x1F
 #define EDP_SDP_HEADER_VALID_PAYLOAD_BYTES 0x1F
 
-- 
2.7.4



[PATCH v3 2/2] drm/rockchip: cdn-dp: send audio infoframe to sink

2017-07-26 Thread Chris Zhong
Some DP/HDMI sink need to receive the audio infoframe to play sound,
especially some multi-channel AV receiver, they need the
channel_allocation from infoframe to config the speakers. Send the
audio infoframe via SDP will make them work properly.

Signed-off-by: Chris Zhong 

---

Changes in v3: None
Changes in v2:
- According to the advice of Sean Paul and Doug
use hdmi_audio_infoframe_pack_payload to pack the buffer
define a SDP_HEADER_SIZE

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 20 
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 27 +++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  |  6 ++
 include/drm/drm_dp_helper.h|  1 +
 4 files changed, 54 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 9b0b058..6a4fc66 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -802,6 +802,7 @@ static int cdn_dp_audio_hw_params(struct device *dev,  void 
*data,
.sample_rate = params->sample_rate,
.channels = params->channels,
};
+   u8 buffer[HDMI_AUDIO_INFOFRAME_SIZE + EDP_SDP_HEADER_SIZE] = { 0 };
int ret;
 
mutex_lock(>lock);
@@ -823,6 +824,25 @@ static int cdn_dp_audio_hw_params(struct device *dev,  
void *data,
goto out;
}
 
+   /*
+* Prepare the infoframe header to SDP header per DP 1.3 spec, Table
+* 2-98.
+*/
+   buffer[0] = 0;
+   buffer[1] = HDMI_INFOFRAME_TYPE_AUDIO;
+   buffer[2] = 0x1b;
+   buffer[3] = 0x48;
+
+   ret = hdmi_audio_infoframe_pack_payload(>cea,
+   [EDP_SDP_HEADER_SIZE],
+   HDMI_AUDIO_INFOFRAME_SIZE);
+   if (ret < 0) {
+   DRM_DEV_ERROR(dev, "Failed to pack audio infoframe: %d\n", ret);
+   goto out;
+   }
+
+   cdn_dp_sdp_write(dp, 0, buffer, sizeof(buffer));
+
ret = cdn_dp_audio_config(dp, );
if (!ret)
dp->audio_info = audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index b14d211..4a818e4 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -286,6 +286,33 @@ int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, 
u8 value)
return ret;
 }
 
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf,
+ u32 buf_len)
+{
+   int idx;
+   u32 *packet = (u32 *)buf;
+   u32 num_packets = buf_len / 4;
+   u8 type;
+
+   if (buf_len < EDP_SDP_HEADER_SIZE) {
+   DRM_DEV_ERROR(dp->dev, "sdp buffer length: %d\n", buf_len);
+   return;
+   }
+
+   type = buf[1];
+
+   for (idx = 0; idx < num_packets; idx++)
+   writel(cpu_to_le32(*packet++), dp->regs + SOURCE_PIF_DATA_WR);
+
+   writel(entry_id, dp->regs + SOURCE_PIF_WR_ADDR);
+
+   writel(F_HOST_WR, dp->regs + SOURCE_PIF_WR_REQ);
+
+   writel(PIF_PKT_TYPE_VALID | F_PACKET_TYPE(type) | entry_id,
+  dp->regs + SOURCE_PIF_PKT_ALLOC_REG);
+   writel(PIF_PKT_ALLOC_WR_EN, dp->regs + SOURCE_PIF_PKT_ALLOC_WR_EN);
+}
+
 int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem,
 u32 i_size, const u32 *d_mem, u32 d_size)
 {
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index c4bbb4a83..6ec0e81 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -424,6 +424,11 @@
 /* Reference cycles when using lane clock as reference */
 #define LANE_REF_CYC   0x8000
 
+#define F_HOST_WR  BIT(0)
+#define PIF_PKT_ALLOC_WR_ENBIT(0)
+#define PIF_PKT_TYPE_VALID (3 << 16)
+#define F_PACKET_TYPE(x)   (((x) & 0xff) << 8)
+
 enum voltage_swing_level {
VOLTAGE_LEVEL_0,
VOLTAGE_LEVEL_1,
@@ -478,5 +483,6 @@ int cdn_dp_set_video_status(struct cdn_dp_device *dp, int 
active);
 int cdn_dp_config_video(struct cdn_dp_device *dp);
 int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio);
 int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable);
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf, u32 
len);
 int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio);
 #endif /* _CDN_DP_REG_H */
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index b17476a..5d5dd07 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -878,6 +878,7 @@ struct edp_sdp_header {
u8 HB3; /* 7:5 reserved, 4:0 number of valid data bytes */
 } __packed;
 
+#define EDP_SDP_HEADER_SIZE4
 #define EDP_SDP_HEADER_REVISION_MASK   0x1F
 #define EDP_SDP_HEADER_VALID_PAYLOAD_BYTES 0x1F
 
-- 
2.7.4



[PATCH v3 1/2] video/hdmi: Introduce helpers for the HDMI audio infoframe payload

2017-07-26 Thread Chris Zhong
The DP is using the same audio infoframe payload as hdmi, per DP 1.3
spec, but it has a different header. Provide a new interface here,
it just packs the payload.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v3:
- add size < HDMI_AUDIO_INFOFRAME_SIZE check according to Doug's advice

Changes in v2: None

 drivers/video/hdmi.c | 66 ++--
 include/linux/hdmi.h |  2 ++
 2 files changed, 50 insertions(+), 18 deletions(-)

diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 1cf907e..9868050 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -240,6 +240,49 @@ int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe 
*frame)
 EXPORT_SYMBOL(hdmi_audio_infoframe_init);
 
 /**
+ * hdmi_audio_infoframe_pack_payload() - write HDMI audio infoframe payload to
+ * binary buffer
+ * @frame: HDMI audio infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Packs the information contained in the @frame structure into a binary
+ * representation that can be written into the corresponding controller
+ * registers.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+ssize_t hdmi_audio_infoframe_pack_payload(struct hdmi_audio_infoframe *frame,
+ void *buffer, size_t size)
+{
+   unsigned char channels;
+   u8 *ptr = buffer;
+
+   if (size < frame->length || size < HDMI_AUDIO_INFOFRAME_SIZE)
+   return -ENOSPC;
+
+   memset(buffer, 0, size);
+
+   if (frame->channels >= 2)
+   channels = frame->channels - 1;
+   else
+   channels = 0;
+
+   ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
+   ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
+(frame->sample_size & 0x3);
+   ptr[2] = frame->coding_type_ext & 0x1f;
+   ptr[3] = frame->channel_allocation;
+   ptr[4] = (frame->level_shift_value & 0xf) << 3;
+
+   if (frame->downmix_inhibit)
+   ptr[4] |= BIT(7);
+
+   return 0;
+}
+EXPORT_SYMBOL(hdmi_audio_infoframe_pack_payload);
+
+/**
  * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer
  * @frame: HDMI audio infoframe
  * @buffer: destination buffer
@@ -256,22 +299,15 @@ EXPORT_SYMBOL(hdmi_audio_infoframe_init);
 ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
  void *buffer, size_t size)
 {
-   unsigned char channels;
u8 *ptr = buffer;
size_t length;
+   int ret;
 
length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
 
if (size < length)
return -ENOSPC;
 
-   memset(buffer, 0, size);
-
-   if (frame->channels >= 2)
-   channels = frame->channels - 1;
-   else
-   channels = 0;
-
ptr[0] = frame->type;
ptr[1] = frame->version;
ptr[2] = frame->length;
@@ -279,16 +315,10 @@ ssize_t hdmi_audio_infoframe_pack(struct 
hdmi_audio_infoframe *frame,
 
/* start infoframe payload */
ptr += HDMI_INFOFRAME_HEADER_SIZE;
-
-   ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
-   ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
-(frame->sample_size & 0x3);
-   ptr[2] = frame->coding_type_ext & 0x1f;
-   ptr[3] = frame->channel_allocation;
-   ptr[4] = (frame->level_shift_value & 0xf) << 3;
-
-   if (frame->downmix_inhibit)
-   ptr[4] |= BIT(7);
+   ret = hdmi_audio_infoframe_pack_payload(frame, ptr,
+   size - HDMI_INFOFRAME_HEADER_SIZE);
+   if (ret)
+   return ret;
 
hdmi_infoframe_set_checksum(buffer, length);
 
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
index d271ff2..a4be132 100644
--- a/include/linux/hdmi.h
+++ b/include/linux/hdmi.h
@@ -272,6 +272,8 @@ struct hdmi_audio_infoframe {
 int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame);
 ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
  void *buffer, size_t size);
+ssize_t hdmi_audio_infoframe_pack_payload(struct hdmi_audio_infoframe *frame,
+ void *buffer, size_t size);
 
 enum hdmi_3d_structure {
HDMI_3D_STRUCTURE_INVALID = -1,
-- 
2.7.4



[PATCH v3 1/2] video/hdmi: Introduce helpers for the HDMI audio infoframe payload

2017-07-26 Thread Chris Zhong
The DP is using the same audio infoframe payload as hdmi, per DP 1.3
spec, but it has a different header. Provide a new interface here,
it just packs the payload.

Signed-off-by: Chris Zhong 
---

Changes in v3:
- add size < HDMI_AUDIO_INFOFRAME_SIZE check according to Doug's advice

Changes in v2: None

 drivers/video/hdmi.c | 66 ++--
 include/linux/hdmi.h |  2 ++
 2 files changed, 50 insertions(+), 18 deletions(-)

diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 1cf907e..9868050 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -240,6 +240,49 @@ int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe 
*frame)
 EXPORT_SYMBOL(hdmi_audio_infoframe_init);
 
 /**
+ * hdmi_audio_infoframe_pack_payload() - write HDMI audio infoframe payload to
+ * binary buffer
+ * @frame: HDMI audio infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Packs the information contained in the @frame structure into a binary
+ * representation that can be written into the corresponding controller
+ * registers.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+ssize_t hdmi_audio_infoframe_pack_payload(struct hdmi_audio_infoframe *frame,
+ void *buffer, size_t size)
+{
+   unsigned char channels;
+   u8 *ptr = buffer;
+
+   if (size < frame->length || size < HDMI_AUDIO_INFOFRAME_SIZE)
+   return -ENOSPC;
+
+   memset(buffer, 0, size);
+
+   if (frame->channels >= 2)
+   channels = frame->channels - 1;
+   else
+   channels = 0;
+
+   ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
+   ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
+(frame->sample_size & 0x3);
+   ptr[2] = frame->coding_type_ext & 0x1f;
+   ptr[3] = frame->channel_allocation;
+   ptr[4] = (frame->level_shift_value & 0xf) << 3;
+
+   if (frame->downmix_inhibit)
+   ptr[4] |= BIT(7);
+
+   return 0;
+}
+EXPORT_SYMBOL(hdmi_audio_infoframe_pack_payload);
+
+/**
  * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer
  * @frame: HDMI audio infoframe
  * @buffer: destination buffer
@@ -256,22 +299,15 @@ EXPORT_SYMBOL(hdmi_audio_infoframe_init);
 ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
  void *buffer, size_t size)
 {
-   unsigned char channels;
u8 *ptr = buffer;
size_t length;
+   int ret;
 
length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
 
if (size < length)
return -ENOSPC;
 
-   memset(buffer, 0, size);
-
-   if (frame->channels >= 2)
-   channels = frame->channels - 1;
-   else
-   channels = 0;
-
ptr[0] = frame->type;
ptr[1] = frame->version;
ptr[2] = frame->length;
@@ -279,16 +315,10 @@ ssize_t hdmi_audio_infoframe_pack(struct 
hdmi_audio_infoframe *frame,
 
/* start infoframe payload */
ptr += HDMI_INFOFRAME_HEADER_SIZE;
-
-   ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
-   ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
-(frame->sample_size & 0x3);
-   ptr[2] = frame->coding_type_ext & 0x1f;
-   ptr[3] = frame->channel_allocation;
-   ptr[4] = (frame->level_shift_value & 0xf) << 3;
-
-   if (frame->downmix_inhibit)
-   ptr[4] |= BIT(7);
+   ret = hdmi_audio_infoframe_pack_payload(frame, ptr,
+   size - HDMI_INFOFRAME_HEADER_SIZE);
+   if (ret)
+   return ret;
 
hdmi_infoframe_set_checksum(buffer, length);
 
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
index d271ff2..a4be132 100644
--- a/include/linux/hdmi.h
+++ b/include/linux/hdmi.h
@@ -272,6 +272,8 @@ struct hdmi_audio_infoframe {
 int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame);
 ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
  void *buffer, size_t size);
+ssize_t hdmi_audio_infoframe_pack_payload(struct hdmi_audio_infoframe *frame,
+ void *buffer, size_t size);
 
 enum hdmi_3d_structure {
HDMI_3D_STRUCTURE_INVALID = -1,
-- 
2.7.4



Re: [PATCH v2 1/2] video/hdmi: Introduce helpers for the HDMI audio infoframe payload

2017-07-18 Thread Chris Zhong

Hi Doug


On Tuesday, July 18, 2017 11:16 PM, Doug Anderson wrote:

Hi,

On Tue, Jul 18, 2017 at 4:20 AM, Chris Zhong <z...@rock-chips.com> wrote:

The DP is using the same audio infoframe payload as hdmi, per DP 1.3
spec, but it has a different header. Provide a new interface here,
it just packs the payload.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v2: None

  drivers/video/hdmi.c | 66 ++--
  include/linux/hdmi.h |  3 ++-
  2 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 1cf907e..e0b041e 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -240,6 +240,49 @@ int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe 
*frame)
  EXPORT_SYMBOL(hdmi_audio_infoframe_init);

  /**
+ * hdmi_audio_infoframe_pack_payload() - write HDMI audio infoframe payload to
+ * binary buffer
+ * @frame: HDMI audio infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Packs the information contained in the @frame structure into a binary
+ * representation that can be written into the corresponding controller
+ * registers.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+ssize_t hdmi_audio_infoframe_pack_payload(struct hdmi_audio_infoframe *frame,
+ void *buffer, size_t size)
+{
+   unsigned char channels;
+   u8 *ptr = buffer;
+
+   if (size < frame->length)

You also need to return -ENOSPC if (size < 5).  That's because below
you always write 5 elements into this array.  I'll leave it to someone
with actual DRM experience to say whether they want a #define of some
sort here.  Probably they do since someone made a #define for
"HDMI_INFOFRAME_HEADER_SIZE".

Also: you don't use frame->length anywhere in this function and it
doesn't seem to be related with packing the payload.  Seems like you
shouldn't check it here.

Actually, I think it should be "if (size < HDMI_AUDIO_INFOFRAME_SIZE)"





+   return -ENOSPC;
+
+   memset(buffer, 0, size);

I don't think the memset belongs here.  It seems like all this
function is doing is setting up ptr[0] through ptr[4] and the memset()
doesn't belong with that, does it?

I think the length of payload is 10 Bytes(DB1~DB10), per audio infoframe 
Format,
but we only use the front 5 Bytes, the back 5 bytes must be 0. If we 
take the 10

bytes as a whole, it make sense.



@@ -256,22 +299,15 @@ EXPORT_SYMBOL(hdmi_audio_infoframe_init);
  ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
   void *buffer, size_t size)
  {
-   unsigned char channels;
 u8 *ptr = buffer;
 size_t length;
+   int ret;

 length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;

 if (size < length)
 return -ENOSPC;

-   memset(buffer, 0, size);

It seems like the memset() belongs here, logically.  This function
deals with the whole buffer so it should be clearing it.


-
-   if (frame->channels >= 2)
-   channels = frame->channels - 1;
-   else
-   channels = 0;
-
 ptr[0] = frame->type;
 ptr[1] = frame->version;
 ptr[2] = frame->length;
@@ -279,16 +315,10 @@ ssize_t hdmi_audio_infoframe_pack(struct 
hdmi_audio_infoframe *frame,

 /* start infoframe payload */
 ptr += HDMI_INFOFRAME_HEADER_SIZE;
-
-   ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
-   ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
-(frame->sample_size & 0x3);
-   ptr[2] = frame->coding_type_ext & 0x1f;
-   ptr[3] = frame->channel_allocation;
-   ptr[4] = (frame->level_shift_value & 0xf) << 3;
-
-   if (frame->downmix_inhibit)
-   ptr[4] |= BIT(7);
+   ret = hdmi_audio_infoframe_pack_payload(frame, ptr,
+   size - HDMI_INFOFRAME_HEADER_SIZE);
+   if (ret)
+   return ret;

 hdmi_infoframe_set_checksum(buffer, length);

diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
index d271ff2..d93c709 100644
--- a/include/linux/hdmi.h
+++ b/include/linux/hdmi.h
@@ -272,7 +272,8 @@ struct hdmi_audio_infoframe {
  int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame);
  ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
   void *buffer, size_t size);
-
+ssize_t hdmi_audio_infoframe_pack_payload(struct hdmi_audio_infoframe *frame,
+ void *buffer, size_t size);

nit: seems like you're changing whitespace here (there used to be a
blank line before the enum).


  enum hdmi_3d_structure {
 HDMI_3D_STRUCTURE_INVALID = -1,
 HDMI_3D_STRUCTURE_FRAME_PACKING = 0,
--
2.7.4






--
Chris Zhong




Re: [PATCH v2 1/2] video/hdmi: Introduce helpers for the HDMI audio infoframe payload

2017-07-18 Thread Chris Zhong

Hi Doug


On Tuesday, July 18, 2017 11:16 PM, Doug Anderson wrote:

Hi,

On Tue, Jul 18, 2017 at 4:20 AM, Chris Zhong  wrote:

The DP is using the same audio infoframe payload as hdmi, per DP 1.3
spec, but it has a different header. Provide a new interface here,
it just packs the payload.

Signed-off-by: Chris Zhong 
---

Changes in v2: None

  drivers/video/hdmi.c | 66 ++--
  include/linux/hdmi.h |  3 ++-
  2 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 1cf907e..e0b041e 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -240,6 +240,49 @@ int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe 
*frame)
  EXPORT_SYMBOL(hdmi_audio_infoframe_init);

  /**
+ * hdmi_audio_infoframe_pack_payload() - write HDMI audio infoframe payload to
+ * binary buffer
+ * @frame: HDMI audio infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Packs the information contained in the @frame structure into a binary
+ * representation that can be written into the corresponding controller
+ * registers.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+ssize_t hdmi_audio_infoframe_pack_payload(struct hdmi_audio_infoframe *frame,
+ void *buffer, size_t size)
+{
+   unsigned char channels;
+   u8 *ptr = buffer;
+
+   if (size < frame->length)

You also need to return -ENOSPC if (size < 5).  That's because below
you always write 5 elements into this array.  I'll leave it to someone
with actual DRM experience to say whether they want a #define of some
sort here.  Probably they do since someone made a #define for
"HDMI_INFOFRAME_HEADER_SIZE".

Also: you don't use frame->length anywhere in this function and it
doesn't seem to be related with packing the payload.  Seems like you
shouldn't check it here.

Actually, I think it should be "if (size < HDMI_AUDIO_INFOFRAME_SIZE)"





+   return -ENOSPC;
+
+   memset(buffer, 0, size);

I don't think the memset belongs here.  It seems like all this
function is doing is setting up ptr[0] through ptr[4] and the memset()
doesn't belong with that, does it?

I think the length of payload is 10 Bytes(DB1~DB10), per audio infoframe 
Format,
but we only use the front 5 Bytes, the back 5 bytes must be 0. If we 
take the 10

bytes as a whole, it make sense.



@@ -256,22 +299,15 @@ EXPORT_SYMBOL(hdmi_audio_infoframe_init);
  ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
   void *buffer, size_t size)
  {
-   unsigned char channels;
 u8 *ptr = buffer;
 size_t length;
+   int ret;

 length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;

 if (size < length)
 return -ENOSPC;

-   memset(buffer, 0, size);

It seems like the memset() belongs here, logically.  This function
deals with the whole buffer so it should be clearing it.


-
-   if (frame->channels >= 2)
-   channels = frame->channels - 1;
-   else
-   channels = 0;
-
 ptr[0] = frame->type;
 ptr[1] = frame->version;
 ptr[2] = frame->length;
@@ -279,16 +315,10 @@ ssize_t hdmi_audio_infoframe_pack(struct 
hdmi_audio_infoframe *frame,

 /* start infoframe payload */
 ptr += HDMI_INFOFRAME_HEADER_SIZE;
-
-   ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
-   ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
-(frame->sample_size & 0x3);
-   ptr[2] = frame->coding_type_ext & 0x1f;
-   ptr[3] = frame->channel_allocation;
-   ptr[4] = (frame->level_shift_value & 0xf) << 3;
-
-   if (frame->downmix_inhibit)
-   ptr[4] |= BIT(7);
+   ret = hdmi_audio_infoframe_pack_payload(frame, ptr,
+   size - HDMI_INFOFRAME_HEADER_SIZE);
+   if (ret)
+   return ret;

 hdmi_infoframe_set_checksum(buffer, length);

diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
index d271ff2..d93c709 100644
--- a/include/linux/hdmi.h
+++ b/include/linux/hdmi.h
@@ -272,7 +272,8 @@ struct hdmi_audio_infoframe {
  int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame);
  ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
   void *buffer, size_t size);
-
+ssize_t hdmi_audio_infoframe_pack_payload(struct hdmi_audio_infoframe *frame,
+ void *buffer, size_t size);

nit: seems like you're changing whitespace here (there used to be a
blank line before the enum).


  enum hdmi_3d_structure {
 HDMI_3D_STRUCTURE_INVALID = -1,
 HDMI_3D_STRUCTURE_FRAME_PACKING = 0,
--
2.7.4






--
Chris Zhong




Re: [PATCH] drm/rockchip: cdn-dp: send audio infoframe to sink

2017-07-18 Thread Chris Zhong

Hi Sean

Thanks for your replying.


On Tuesday, July 18, 2017 04:23 AM, Sean Paul wrote:

On Sat, Jul 15, 2017 at 07:00:18PM +0800, Chris Zhong wrote:

Some DP/HDMI sink need to receive the audio infoframe to play sound,
especially some multi-channel AV receiver, they need the
channel_allocation from infoframe to config the speakers. Send the
audio infoframe via SDP will make them work properly.

Signed-off-by: Chris Zhong <z...@rock-chips.com>

Hi Chris,
Thanks for the patch, please see comments below.


---

  drivers/gpu/drm/rockchip/cdn-dp-core.c | 20 
  drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 19 +++
  drivers/gpu/drm/rockchip/cdn-dp-reg.h  |  6 ++
  3 files changed, 45 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 9b0b058..e59ca47 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -802,6 +802,7 @@ static int cdn_dp_audio_hw_params(struct device *dev,  void 
*data,
.sample_rate = params->sample_rate,
.channels = params->channels,
};
+   u8 buffer[14];

Why 14?

I think you should probably have buffer[HDMI_AUDIO_INFOFRAME_SIZE +
SDP_HEADER_SIZE] so the reader knows how you arrived at this value.


int ret;
  
  	mutex_lock(>lock);

@@ -823,6 +824,25 @@ static int cdn_dp_audio_hw_params(struct device *dev,  
void *data,
goto out;
}
  
+	memset(buffer, 0, sizeof(buffer));

+
+   ret = hdmi_audio_infoframe_pack(>cea, buffer, sizeof(buffer));
+   if (ret < 0) {
+   DRM_DEV_ERROR(dev, "Failed to pack audio infoframe: %d\n", ret);
+   goto out;
+   }
+
+   /*
+* Change the infoframe header to SDP header per DP 1.3 spec, Table
+* 2-98.
+*/
+   buffer[0] = 0;
+   buffer[1] = HDMI_INFOFRAME_TYPE_AUDIO;
+   buffer[2] = 0x1b;
+   buffer[3] = 0x48;

Instead of doing this, consider splitting up hdmi_audio_infoframe_pack into
hdmi_audio_infoframe_pack and hdmi_audio_infoframe_pack_payload. The first
function does everything, while the second just packs the payload, then you can
set the SDP header independently.


+
+   cdn_dp_sdp_write(dp, 0, buffer, sizeof(buffer));
+
ret = cdn_dp_audio_config(dp, );
if (!ret)
dp->audio_info = audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index b14d211..8907db0 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -951,6 +951,25 @@ static void cdn_dp_audio_config_spdif(struct cdn_dp_device 
*dp)
clk_set_rate(dp->spdif_clk, CDN_DP_SPDIF_CLK);
  }
  
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf, u32 len)

+{
+   int idx;
+   u32 *packet = (u32 *)buf;
+   u32 length = len / 4;

length and len are pretty terrible names, it would be quite easy to use the
wrong one. Consider more descriptive names (ie: buf_len and num_packets).


+   u8 type = buf[1];

Check for len < 0?


+
+   for (idx = 0; idx < length; idx++)
+   writel(cpu_to_le32(*packet++), dp->regs + SOURCE_PIF_DATA_WR);
+
+   writel(entry_id, dp->regs + SOURCE_PIF_WR_ADDR);
+
+   writel(F_HOST_WR, dp->regs + SOURCE_PIF_WR_REQ);
+
+   writel(PIF_PKT_TYPE_VALID | F_PACKET_TYPE(type) | entry_id,
+  dp->regs + SOURCE_PIF_PKT_ALLOC_REG);
+   writel(PIF_PKT_ALLOC_WR_EN, dp->regs + SOURCE_PIF_PKT_ALLOC_WR_EN);
+}
+
  int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio)
  {
int ret;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index c4bbb4a83..6ec0e81 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -424,6 +424,11 @@
  /* Reference cycles when using lane clock as reference */
  #define LANE_REF_CYC  0x8000
  
+#define F_HOST_WR		BIT(0)

+#define PIF_PKT_ALLOC_WR_ENBIT(0)
+#define PIF_PKT_TYPE_VALID (3 << 16)
+#define F_PACKET_TYPE(x)   (((x) & 0xff) << 8)

Can you tuck these #defines under the definition of SOURCE_PIF_PKT_ALLOC_REG, so
we know which register they apply to?


Considering the existing code style of this file, can we keep these 
defines here?



+
  enum voltage_swing_level {
VOLTAGE_LEVEL_0,
VOLTAGE_LEVEL_1,
@@ -478,5 +483,6 @@ int cdn_dp_set_video_status(struct cdn_dp_device *dp, int 
active);
  int cdn_dp_config_video(struct cdn_dp_device *dp);
  int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio);
  int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable);
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf, u32 
len);
  int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio);
  #endif /* _CDN_DP_REG_H */
--
2.6.3



--
Chris Zhong




Re: [PATCH] drm/rockchip: cdn-dp: send audio infoframe to sink

2017-07-18 Thread Chris Zhong

Hi Sean

Thanks for your replying.


On Tuesday, July 18, 2017 04:23 AM, Sean Paul wrote:

On Sat, Jul 15, 2017 at 07:00:18PM +0800, Chris Zhong wrote:

Some DP/HDMI sink need to receive the audio infoframe to play sound,
especially some multi-channel AV receiver, they need the
channel_allocation from infoframe to config the speakers. Send the
audio infoframe via SDP will make them work properly.

Signed-off-by: Chris Zhong 

Hi Chris,
Thanks for the patch, please see comments below.


---

  drivers/gpu/drm/rockchip/cdn-dp-core.c | 20 
  drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 19 +++
  drivers/gpu/drm/rockchip/cdn-dp-reg.h  |  6 ++
  3 files changed, 45 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 9b0b058..e59ca47 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -802,6 +802,7 @@ static int cdn_dp_audio_hw_params(struct device *dev,  void 
*data,
.sample_rate = params->sample_rate,
.channels = params->channels,
};
+   u8 buffer[14];

Why 14?

I think you should probably have buffer[HDMI_AUDIO_INFOFRAME_SIZE +
SDP_HEADER_SIZE] so the reader knows how you arrived at this value.


int ret;
  
  	mutex_lock(>lock);

@@ -823,6 +824,25 @@ static int cdn_dp_audio_hw_params(struct device *dev,  
void *data,
goto out;
}
  
+	memset(buffer, 0, sizeof(buffer));

+
+   ret = hdmi_audio_infoframe_pack(>cea, buffer, sizeof(buffer));
+   if (ret < 0) {
+   DRM_DEV_ERROR(dev, "Failed to pack audio infoframe: %d\n", ret);
+   goto out;
+   }
+
+   /*
+* Change the infoframe header to SDP header per DP 1.3 spec, Table
+* 2-98.
+*/
+   buffer[0] = 0;
+   buffer[1] = HDMI_INFOFRAME_TYPE_AUDIO;
+   buffer[2] = 0x1b;
+   buffer[3] = 0x48;

Instead of doing this, consider splitting up hdmi_audio_infoframe_pack into
hdmi_audio_infoframe_pack and hdmi_audio_infoframe_pack_payload. The first
function does everything, while the second just packs the payload, then you can
set the SDP header independently.


+
+   cdn_dp_sdp_write(dp, 0, buffer, sizeof(buffer));
+
ret = cdn_dp_audio_config(dp, );
if (!ret)
dp->audio_info = audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index b14d211..8907db0 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -951,6 +951,25 @@ static void cdn_dp_audio_config_spdif(struct cdn_dp_device 
*dp)
clk_set_rate(dp->spdif_clk, CDN_DP_SPDIF_CLK);
  }
  
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf, u32 len)

+{
+   int idx;
+   u32 *packet = (u32 *)buf;
+   u32 length = len / 4;

length and len are pretty terrible names, it would be quite easy to use the
wrong one. Consider more descriptive names (ie: buf_len and num_packets).


+   u8 type = buf[1];

Check for len < 0?


+
+   for (idx = 0; idx < length; idx++)
+   writel(cpu_to_le32(*packet++), dp->regs + SOURCE_PIF_DATA_WR);
+
+   writel(entry_id, dp->regs + SOURCE_PIF_WR_ADDR);
+
+   writel(F_HOST_WR, dp->regs + SOURCE_PIF_WR_REQ);
+
+   writel(PIF_PKT_TYPE_VALID | F_PACKET_TYPE(type) | entry_id,
+  dp->regs + SOURCE_PIF_PKT_ALLOC_REG);
+   writel(PIF_PKT_ALLOC_WR_EN, dp->regs + SOURCE_PIF_PKT_ALLOC_WR_EN);
+}
+
  int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio)
  {
int ret;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index c4bbb4a83..6ec0e81 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -424,6 +424,11 @@
  /* Reference cycles when using lane clock as reference */
  #define LANE_REF_CYC  0x8000
  
+#define F_HOST_WR		BIT(0)

+#define PIF_PKT_ALLOC_WR_ENBIT(0)
+#define PIF_PKT_TYPE_VALID (3 << 16)
+#define F_PACKET_TYPE(x)   (((x) & 0xff) << 8)

Can you tuck these #defines under the definition of SOURCE_PIF_PKT_ALLOC_REG, so
we know which register they apply to?


Considering the existing code style of this file, can we keep these 
defines here?



+
  enum voltage_swing_level {
VOLTAGE_LEVEL_0,
VOLTAGE_LEVEL_1,
@@ -478,5 +483,6 @@ int cdn_dp_set_video_status(struct cdn_dp_device *dp, int 
active);
  int cdn_dp_config_video(struct cdn_dp_device *dp);
  int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio);
  int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable);
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf, u32 
len);
  int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio);
  #endif /* _CDN_DP_REG_H */
--
2.6.3



--
Chris Zhong




[PATCH v2 1/2] video/hdmi: Introduce helpers for the HDMI audio infoframe payload

2017-07-18 Thread Chris Zhong
The DP is using the same audio infoframe payload as hdmi, per DP 1.3
spec, but it has a different header. Provide a new interface here,
it just packs the payload.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v2: None

 drivers/video/hdmi.c | 66 ++--
 include/linux/hdmi.h |  3 ++-
 2 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 1cf907e..e0b041e 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -240,6 +240,49 @@ int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe 
*frame)
 EXPORT_SYMBOL(hdmi_audio_infoframe_init);
 
 /**
+ * hdmi_audio_infoframe_pack_payload() - write HDMI audio infoframe payload to
+ * binary buffer
+ * @frame: HDMI audio infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Packs the information contained in the @frame structure into a binary
+ * representation that can be written into the corresponding controller
+ * registers.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+ssize_t hdmi_audio_infoframe_pack_payload(struct hdmi_audio_infoframe *frame,
+ void *buffer, size_t size)
+{
+   unsigned char channels;
+   u8 *ptr = buffer;
+
+   if (size < frame->length)
+   return -ENOSPC;
+
+   memset(buffer, 0, size);
+
+   if (frame->channels >= 2)
+   channels = frame->channels - 1;
+   else
+   channels = 0;
+
+   ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
+   ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
+(frame->sample_size & 0x3);
+   ptr[2] = frame->coding_type_ext & 0x1f;
+   ptr[3] = frame->channel_allocation;
+   ptr[4] = (frame->level_shift_value & 0xf) << 3;
+
+   if (frame->downmix_inhibit)
+   ptr[4] |= BIT(7);
+
+   return 0;
+}
+EXPORT_SYMBOL(hdmi_audio_infoframe_pack_payload);
+
+/**
  * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer
  * @frame: HDMI audio infoframe
  * @buffer: destination buffer
@@ -256,22 +299,15 @@ EXPORT_SYMBOL(hdmi_audio_infoframe_init);
 ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
  void *buffer, size_t size)
 {
-   unsigned char channels;
u8 *ptr = buffer;
size_t length;
+   int ret;
 
length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
 
if (size < length)
return -ENOSPC;
 
-   memset(buffer, 0, size);
-
-   if (frame->channels >= 2)
-   channels = frame->channels - 1;
-   else
-   channels = 0;
-
ptr[0] = frame->type;
ptr[1] = frame->version;
ptr[2] = frame->length;
@@ -279,16 +315,10 @@ ssize_t hdmi_audio_infoframe_pack(struct 
hdmi_audio_infoframe *frame,
 
/* start infoframe payload */
ptr += HDMI_INFOFRAME_HEADER_SIZE;
-
-   ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
-   ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
-(frame->sample_size & 0x3);
-   ptr[2] = frame->coding_type_ext & 0x1f;
-   ptr[3] = frame->channel_allocation;
-   ptr[4] = (frame->level_shift_value & 0xf) << 3;
-
-   if (frame->downmix_inhibit)
-   ptr[4] |= BIT(7);
+   ret = hdmi_audio_infoframe_pack_payload(frame, ptr,
+   size - HDMI_INFOFRAME_HEADER_SIZE);
+   if (ret)
+   return ret;
 
hdmi_infoframe_set_checksum(buffer, length);
 
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
index d271ff2..d93c709 100644
--- a/include/linux/hdmi.h
+++ b/include/linux/hdmi.h
@@ -272,7 +272,8 @@ struct hdmi_audio_infoframe {
 int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame);
 ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
  void *buffer, size_t size);
-
+ssize_t hdmi_audio_infoframe_pack_payload(struct hdmi_audio_infoframe *frame,
+ void *buffer, size_t size);
 enum hdmi_3d_structure {
HDMI_3D_STRUCTURE_INVALID = -1,
HDMI_3D_STRUCTURE_FRAME_PACKING = 0,
-- 
2.7.4



[PATCH v2 2/2] drm/rockchip: cdn-dp: send audio infoframe to sink

2017-07-18 Thread Chris Zhong
Some DP/HDMI sink need to receive the audio infoframe to play sound,
especially some multi-channel AV receiver, they need the
channel_allocation from infoframe to config the speakers. Send the
audio infoframe via SDP will make them work properly.

Signed-off-by: Chris Zhong <z...@rock-chips.com>

---

Changes in v2:
- According to the advice of Sean Paul and Doug
use hdmi_audio_infoframe_pack_payload to pack the buffer
define a SDP_HEADER_SIZE

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 20 
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 27 +++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  |  6 ++
 include/drm/drm_dp_helper.h|  1 +
 4 files changed, 54 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 9b0b058..6a4fc66 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -802,6 +802,7 @@ static int cdn_dp_audio_hw_params(struct device *dev,  void 
*data,
.sample_rate = params->sample_rate,
.channels = params->channels,
};
+   u8 buffer[HDMI_AUDIO_INFOFRAME_SIZE + EDP_SDP_HEADER_SIZE] = { 0 };
int ret;
 
mutex_lock(>lock);
@@ -823,6 +824,25 @@ static int cdn_dp_audio_hw_params(struct device *dev,  
void *data,
goto out;
}
 
+   /*
+* Prepare the infoframe header to SDP header per DP 1.3 spec, Table
+* 2-98.
+*/
+   buffer[0] = 0;
+   buffer[1] = HDMI_INFOFRAME_TYPE_AUDIO;
+   buffer[2] = 0x1b;
+   buffer[3] = 0x48;
+
+   ret = hdmi_audio_infoframe_pack_payload(>cea,
+   [EDP_SDP_HEADER_SIZE],
+   HDMI_AUDIO_INFOFRAME_SIZE);
+   if (ret < 0) {
+   DRM_DEV_ERROR(dev, "Failed to pack audio infoframe: %d\n", ret);
+   goto out;
+   }
+
+   cdn_dp_sdp_write(dp, 0, buffer, sizeof(buffer));
+
ret = cdn_dp_audio_config(dp, );
if (!ret)
dp->audio_info = audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index b14d211..4a818e4 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -286,6 +286,33 @@ int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, 
u8 value)
return ret;
 }
 
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf,
+ u32 buf_len)
+{
+   int idx;
+   u32 *packet = (u32 *)buf;
+   u32 num_packets = buf_len / 4;
+   u8 type;
+
+   if (buf_len < EDP_SDP_HEADER_SIZE) {
+   DRM_DEV_ERROR(dp->dev, "sdp buffer length: %d\n", buf_len);
+   return;
+   }
+
+   type = buf[1];
+
+   for (idx = 0; idx < num_packets; idx++)
+   writel(cpu_to_le32(*packet++), dp->regs + SOURCE_PIF_DATA_WR);
+
+   writel(entry_id, dp->regs + SOURCE_PIF_WR_ADDR);
+
+   writel(F_HOST_WR, dp->regs + SOURCE_PIF_WR_REQ);
+
+   writel(PIF_PKT_TYPE_VALID | F_PACKET_TYPE(type) | entry_id,
+  dp->regs + SOURCE_PIF_PKT_ALLOC_REG);
+   writel(PIF_PKT_ALLOC_WR_EN, dp->regs + SOURCE_PIF_PKT_ALLOC_WR_EN);
+}
+
 int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem,
 u32 i_size, const u32 *d_mem, u32 d_size)
 {
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index c4bbb4a83..6ec0e81 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -424,6 +424,11 @@
 /* Reference cycles when using lane clock as reference */
 #define LANE_REF_CYC   0x8000
 
+#define F_HOST_WR  BIT(0)
+#define PIF_PKT_ALLOC_WR_ENBIT(0)
+#define PIF_PKT_TYPE_VALID (3 << 16)
+#define F_PACKET_TYPE(x)   (((x) & 0xff) << 8)
+
 enum voltage_swing_level {
VOLTAGE_LEVEL_0,
VOLTAGE_LEVEL_1,
@@ -478,5 +483,6 @@ int cdn_dp_set_video_status(struct cdn_dp_device *dp, int 
active);
 int cdn_dp_config_video(struct cdn_dp_device *dp);
 int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio);
 int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable);
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf, u32 
len);
 int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio);
 #endif /* _CDN_DP_REG_H */
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index b17476a..5d5dd07 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -878,6 +878,7 @@ struct edp_sdp_header {
u8 HB3; /* 7:5 reserved, 4:0 number of valid data bytes */
 } __packed;
 
+#define EDP_SDP_HEADER_SIZE4
 #define EDP_SDP_HEADER_REVISION_MASK   0x1F
 #define EDP_SDP_HEADER_VALID_PAYLOAD_BYTES 0x1F
 
-- 
2.7.4



[PATCH v2 1/2] video/hdmi: Introduce helpers for the HDMI audio infoframe payload

2017-07-18 Thread Chris Zhong
The DP is using the same audio infoframe payload as hdmi, per DP 1.3
spec, but it has a different header. Provide a new interface here,
it just packs the payload.

Signed-off-by: Chris Zhong 
---

Changes in v2: None

 drivers/video/hdmi.c | 66 ++--
 include/linux/hdmi.h |  3 ++-
 2 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 1cf907e..e0b041e 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -240,6 +240,49 @@ int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe 
*frame)
 EXPORT_SYMBOL(hdmi_audio_infoframe_init);
 
 /**
+ * hdmi_audio_infoframe_pack_payload() - write HDMI audio infoframe payload to
+ * binary buffer
+ * @frame: HDMI audio infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Packs the information contained in the @frame structure into a binary
+ * representation that can be written into the corresponding controller
+ * registers.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+ssize_t hdmi_audio_infoframe_pack_payload(struct hdmi_audio_infoframe *frame,
+ void *buffer, size_t size)
+{
+   unsigned char channels;
+   u8 *ptr = buffer;
+
+   if (size < frame->length)
+   return -ENOSPC;
+
+   memset(buffer, 0, size);
+
+   if (frame->channels >= 2)
+   channels = frame->channels - 1;
+   else
+   channels = 0;
+
+   ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
+   ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
+(frame->sample_size & 0x3);
+   ptr[2] = frame->coding_type_ext & 0x1f;
+   ptr[3] = frame->channel_allocation;
+   ptr[4] = (frame->level_shift_value & 0xf) << 3;
+
+   if (frame->downmix_inhibit)
+   ptr[4] |= BIT(7);
+
+   return 0;
+}
+EXPORT_SYMBOL(hdmi_audio_infoframe_pack_payload);
+
+/**
  * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer
  * @frame: HDMI audio infoframe
  * @buffer: destination buffer
@@ -256,22 +299,15 @@ EXPORT_SYMBOL(hdmi_audio_infoframe_init);
 ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
  void *buffer, size_t size)
 {
-   unsigned char channels;
u8 *ptr = buffer;
size_t length;
+   int ret;
 
length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
 
if (size < length)
return -ENOSPC;
 
-   memset(buffer, 0, size);
-
-   if (frame->channels >= 2)
-   channels = frame->channels - 1;
-   else
-   channels = 0;
-
ptr[0] = frame->type;
ptr[1] = frame->version;
ptr[2] = frame->length;
@@ -279,16 +315,10 @@ ssize_t hdmi_audio_infoframe_pack(struct 
hdmi_audio_infoframe *frame,
 
/* start infoframe payload */
ptr += HDMI_INFOFRAME_HEADER_SIZE;
-
-   ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
-   ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
-(frame->sample_size & 0x3);
-   ptr[2] = frame->coding_type_ext & 0x1f;
-   ptr[3] = frame->channel_allocation;
-   ptr[4] = (frame->level_shift_value & 0xf) << 3;
-
-   if (frame->downmix_inhibit)
-   ptr[4] |= BIT(7);
+   ret = hdmi_audio_infoframe_pack_payload(frame, ptr,
+   size - HDMI_INFOFRAME_HEADER_SIZE);
+   if (ret)
+   return ret;
 
hdmi_infoframe_set_checksum(buffer, length);
 
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
index d271ff2..d93c709 100644
--- a/include/linux/hdmi.h
+++ b/include/linux/hdmi.h
@@ -272,7 +272,8 @@ struct hdmi_audio_infoframe {
 int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame);
 ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
  void *buffer, size_t size);
-
+ssize_t hdmi_audio_infoframe_pack_payload(struct hdmi_audio_infoframe *frame,
+ void *buffer, size_t size);
 enum hdmi_3d_structure {
HDMI_3D_STRUCTURE_INVALID = -1,
HDMI_3D_STRUCTURE_FRAME_PACKING = 0,
-- 
2.7.4



[PATCH v2 2/2] drm/rockchip: cdn-dp: send audio infoframe to sink

2017-07-18 Thread Chris Zhong
Some DP/HDMI sink need to receive the audio infoframe to play sound,
especially some multi-channel AV receiver, they need the
channel_allocation from infoframe to config the speakers. Send the
audio infoframe via SDP will make them work properly.

Signed-off-by: Chris Zhong 

---

Changes in v2:
- According to the advice of Sean Paul and Doug
use hdmi_audio_infoframe_pack_payload to pack the buffer
define a SDP_HEADER_SIZE

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 20 
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 27 +++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  |  6 ++
 include/drm/drm_dp_helper.h|  1 +
 4 files changed, 54 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 9b0b058..6a4fc66 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -802,6 +802,7 @@ static int cdn_dp_audio_hw_params(struct device *dev,  void 
*data,
.sample_rate = params->sample_rate,
.channels = params->channels,
};
+   u8 buffer[HDMI_AUDIO_INFOFRAME_SIZE + EDP_SDP_HEADER_SIZE] = { 0 };
int ret;
 
mutex_lock(>lock);
@@ -823,6 +824,25 @@ static int cdn_dp_audio_hw_params(struct device *dev,  
void *data,
goto out;
}
 
+   /*
+* Prepare the infoframe header to SDP header per DP 1.3 spec, Table
+* 2-98.
+*/
+   buffer[0] = 0;
+   buffer[1] = HDMI_INFOFRAME_TYPE_AUDIO;
+   buffer[2] = 0x1b;
+   buffer[3] = 0x48;
+
+   ret = hdmi_audio_infoframe_pack_payload(>cea,
+   [EDP_SDP_HEADER_SIZE],
+   HDMI_AUDIO_INFOFRAME_SIZE);
+   if (ret < 0) {
+   DRM_DEV_ERROR(dev, "Failed to pack audio infoframe: %d\n", ret);
+   goto out;
+   }
+
+   cdn_dp_sdp_write(dp, 0, buffer, sizeof(buffer));
+
ret = cdn_dp_audio_config(dp, );
if (!ret)
dp->audio_info = audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index b14d211..4a818e4 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -286,6 +286,33 @@ int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, 
u8 value)
return ret;
 }
 
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf,
+ u32 buf_len)
+{
+   int idx;
+   u32 *packet = (u32 *)buf;
+   u32 num_packets = buf_len / 4;
+   u8 type;
+
+   if (buf_len < EDP_SDP_HEADER_SIZE) {
+   DRM_DEV_ERROR(dp->dev, "sdp buffer length: %d\n", buf_len);
+   return;
+   }
+
+   type = buf[1];
+
+   for (idx = 0; idx < num_packets; idx++)
+   writel(cpu_to_le32(*packet++), dp->regs + SOURCE_PIF_DATA_WR);
+
+   writel(entry_id, dp->regs + SOURCE_PIF_WR_ADDR);
+
+   writel(F_HOST_WR, dp->regs + SOURCE_PIF_WR_REQ);
+
+   writel(PIF_PKT_TYPE_VALID | F_PACKET_TYPE(type) | entry_id,
+  dp->regs + SOURCE_PIF_PKT_ALLOC_REG);
+   writel(PIF_PKT_ALLOC_WR_EN, dp->regs + SOURCE_PIF_PKT_ALLOC_WR_EN);
+}
+
 int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem,
 u32 i_size, const u32 *d_mem, u32 d_size)
 {
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index c4bbb4a83..6ec0e81 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -424,6 +424,11 @@
 /* Reference cycles when using lane clock as reference */
 #define LANE_REF_CYC   0x8000
 
+#define F_HOST_WR  BIT(0)
+#define PIF_PKT_ALLOC_WR_ENBIT(0)
+#define PIF_PKT_TYPE_VALID (3 << 16)
+#define F_PACKET_TYPE(x)   (((x) & 0xff) << 8)
+
 enum voltage_swing_level {
VOLTAGE_LEVEL_0,
VOLTAGE_LEVEL_1,
@@ -478,5 +483,6 @@ int cdn_dp_set_video_status(struct cdn_dp_device *dp, int 
active);
 int cdn_dp_config_video(struct cdn_dp_device *dp);
 int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio);
 int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable);
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf, u32 
len);
 int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio);
 #endif /* _CDN_DP_REG_H */
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index b17476a..5d5dd07 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -878,6 +878,7 @@ struct edp_sdp_header {
u8 HB3; /* 7:5 reserved, 4:0 number of valid data bytes */
 } __packed;
 
+#define EDP_SDP_HEADER_SIZE4
 #define EDP_SDP_HEADER_REVISION_MASK   0x1F
 #define EDP_SDP_HEADER_VALID_PAYLOAD_BYTES 0x1F
 
-- 
2.7.4



[PATCH] drm/rockchip: cdn-dp: send audio infoframe to sink

2017-07-15 Thread Chris Zhong
Some DP/HDMI sink need to receive the audio infoframe to play sound,
especially some multi-channel AV receiver, they need the
channel_allocation from infoframe to config the speakers. Send the
audio infoframe via SDP will make them work properly.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 20 
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 19 +++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  |  6 ++
 3 files changed, 45 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 9b0b058..e59ca47 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -802,6 +802,7 @@ static int cdn_dp_audio_hw_params(struct device *dev,  void 
*data,
.sample_rate = params->sample_rate,
.channels = params->channels,
};
+   u8 buffer[14];
int ret;
 
mutex_lock(>lock);
@@ -823,6 +824,25 @@ static int cdn_dp_audio_hw_params(struct device *dev,  
void *data,
goto out;
}
 
+   memset(buffer, 0, sizeof(buffer));
+
+   ret = hdmi_audio_infoframe_pack(>cea, buffer, sizeof(buffer));
+   if (ret < 0) {
+   DRM_DEV_ERROR(dev, "Failed to pack audio infoframe: %d\n", ret);
+   goto out;
+   }
+
+   /*
+* Change the infoframe header to SDP header per DP 1.3 spec, Table
+* 2-98.
+*/
+   buffer[0] = 0;
+   buffer[1] = HDMI_INFOFRAME_TYPE_AUDIO;
+   buffer[2] = 0x1b;
+   buffer[3] = 0x48;
+
+   cdn_dp_sdp_write(dp, 0, buffer, sizeof(buffer));
+
ret = cdn_dp_audio_config(dp, );
if (!ret)
dp->audio_info = audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index b14d211..8907db0 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -951,6 +951,25 @@ static void cdn_dp_audio_config_spdif(struct cdn_dp_device 
*dp)
clk_set_rate(dp->spdif_clk, CDN_DP_SPDIF_CLK);
 }
 
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf, u32 len)
+{
+   int idx;
+   u32 *packet = (u32 *)buf;
+   u32 length = len / 4;
+   u8 type = buf[1];
+
+   for (idx = 0; idx < length; idx++)
+   writel(cpu_to_le32(*packet++), dp->regs + SOURCE_PIF_DATA_WR);
+
+   writel(entry_id, dp->regs + SOURCE_PIF_WR_ADDR);
+
+   writel(F_HOST_WR, dp->regs + SOURCE_PIF_WR_REQ);
+
+   writel(PIF_PKT_TYPE_VALID | F_PACKET_TYPE(type) | entry_id,
+  dp->regs + SOURCE_PIF_PKT_ALLOC_REG);
+   writel(PIF_PKT_ALLOC_WR_EN, dp->regs + SOURCE_PIF_PKT_ALLOC_WR_EN);
+}
+
 int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio)
 {
int ret;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index c4bbb4a83..6ec0e81 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -424,6 +424,11 @@
 /* Reference cycles when using lane clock as reference */
 #define LANE_REF_CYC   0x8000
 
+#define F_HOST_WR  BIT(0)
+#define PIF_PKT_ALLOC_WR_ENBIT(0)
+#define PIF_PKT_TYPE_VALID (3 << 16)
+#define F_PACKET_TYPE(x)   (((x) & 0xff) << 8)
+
 enum voltage_swing_level {
VOLTAGE_LEVEL_0,
VOLTAGE_LEVEL_1,
@@ -478,5 +483,6 @@ int cdn_dp_set_video_status(struct cdn_dp_device *dp, int 
active);
 int cdn_dp_config_video(struct cdn_dp_device *dp);
 int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio);
 int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable);
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf, u32 
len);
 int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio);
 #endif /* _CDN_DP_REG_H */
-- 
2.6.3



[PATCH] drm/rockchip: cdn-dp: send audio infoframe to sink

2017-07-15 Thread Chris Zhong
Some DP/HDMI sink need to receive the audio infoframe to play sound,
especially some multi-channel AV receiver, they need the
channel_allocation from infoframe to config the speakers. Send the
audio infoframe via SDP will make them work properly.

Signed-off-by: Chris Zhong 
---

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 20 
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 19 +++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  |  6 ++
 3 files changed, 45 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 9b0b058..e59ca47 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -802,6 +802,7 @@ static int cdn_dp_audio_hw_params(struct device *dev,  void 
*data,
.sample_rate = params->sample_rate,
.channels = params->channels,
};
+   u8 buffer[14];
int ret;
 
mutex_lock(>lock);
@@ -823,6 +824,25 @@ static int cdn_dp_audio_hw_params(struct device *dev,  
void *data,
goto out;
}
 
+   memset(buffer, 0, sizeof(buffer));
+
+   ret = hdmi_audio_infoframe_pack(>cea, buffer, sizeof(buffer));
+   if (ret < 0) {
+   DRM_DEV_ERROR(dev, "Failed to pack audio infoframe: %d\n", ret);
+   goto out;
+   }
+
+   /*
+* Change the infoframe header to SDP header per DP 1.3 spec, Table
+* 2-98.
+*/
+   buffer[0] = 0;
+   buffer[1] = HDMI_INFOFRAME_TYPE_AUDIO;
+   buffer[2] = 0x1b;
+   buffer[3] = 0x48;
+
+   cdn_dp_sdp_write(dp, 0, buffer, sizeof(buffer));
+
ret = cdn_dp_audio_config(dp, );
if (!ret)
dp->audio_info = audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index b14d211..8907db0 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -951,6 +951,25 @@ static void cdn_dp_audio_config_spdif(struct cdn_dp_device 
*dp)
clk_set_rate(dp->spdif_clk, CDN_DP_SPDIF_CLK);
 }
 
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf, u32 len)
+{
+   int idx;
+   u32 *packet = (u32 *)buf;
+   u32 length = len / 4;
+   u8 type = buf[1];
+
+   for (idx = 0; idx < length; idx++)
+   writel(cpu_to_le32(*packet++), dp->regs + SOURCE_PIF_DATA_WR);
+
+   writel(entry_id, dp->regs + SOURCE_PIF_WR_ADDR);
+
+   writel(F_HOST_WR, dp->regs + SOURCE_PIF_WR_REQ);
+
+   writel(PIF_PKT_TYPE_VALID | F_PACKET_TYPE(type) | entry_id,
+  dp->regs + SOURCE_PIF_PKT_ALLOC_REG);
+   writel(PIF_PKT_ALLOC_WR_EN, dp->regs + SOURCE_PIF_PKT_ALLOC_WR_EN);
+}
+
 int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio)
 {
int ret;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index c4bbb4a83..6ec0e81 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -424,6 +424,11 @@
 /* Reference cycles when using lane clock as reference */
 #define LANE_REF_CYC   0x8000
 
+#define F_HOST_WR  BIT(0)
+#define PIF_PKT_ALLOC_WR_ENBIT(0)
+#define PIF_PKT_TYPE_VALID (3 << 16)
+#define F_PACKET_TYPE(x)   (((x) & 0xff) << 8)
+
 enum voltage_swing_level {
VOLTAGE_LEVEL_0,
VOLTAGE_LEVEL_1,
@@ -478,5 +483,6 @@ int cdn_dp_set_video_status(struct cdn_dp_device *dp, int 
active);
 int cdn_dp_config_video(struct cdn_dp_device *dp);
 int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio);
 int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable);
+void cdn_dp_sdp_write(struct cdn_dp_device *dp, int entry_id, u8 *buf, u32 
len);
 int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio);
 #endif /* _CDN_DP_REG_H */
-- 
2.6.3



[PATCH v4 2/2] drm/panel: add innolux,p079zca panel driver

2017-03-23 Thread Chris Zhong
Support Innolux P079ZCA 7.85" 768x1024 TFT LCD panel, it is a MIPI DSI
panel.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
Tested-by: Brian Norris <briannor...@chromium.org>
---

Changes in v4:
- remove backlight check after probe
- add bpc info

Changes in v3:
- printk err after regulator_disable(innolux->supply)

Changes in v2:
- add some error check
- always use Low power mode to send commend
- add comments for all the sleep
- use DRM_DEV_ERROR instead of dev_err

 drivers/gpu/drm/panel/Kconfig |  11 +
 drivers/gpu/drm/panel/Makefile|   1 +
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 340 ++
 3 files changed, 352 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-innolux-p079zca.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 62aba97..99dd010 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -18,6 +18,17 @@ config DRM_PANEL_SIMPLE
  that it can be automatically turned off when the panel goes into a
  low power state.
 
+config DRM_PANEL_INNOLUX_P079ZCA
+   tristate "Innolux P079ZCA panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   depends on BACKLIGHT_CLASS_DEVICE
+   help
+ Say Y here if you want to enable support for Innolux P079ZCA
+ TFT-LCD modules. The panel has a 1024x768 resolution and uses
+ 24 bit RGB per pixel. It provides a MIPI DSI interface to
+ the host and has a built-in LED backlight.
+
 config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index a5c7ec0..bda2aa4 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
+obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
 obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
new file mode 100644
index 000..6ba9344
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct innolux_panel {
+   struct drm_panel base;
+   struct mipi_dsi_device *link;
+
+   struct backlight_device *backlight;
+   struct regulator *supply;
+   struct gpio_desc *enable_gpio;
+
+   bool prepared;
+   bool enabled;
+};
+
+static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel)
+{
+   return container_of(panel, struct innolux_panel, base);
+}
+
+static int innolux_panel_disable(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->enabled)
+   return 0;
+
+   innolux->backlight->props.power = FB_BLANK_POWERDOWN;
+   backlight_update_status(innolux->backlight);
+
+   err = mipi_dsi_dcs_set_display_off(innolux->link);
+   if (err < 0)
+   DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n",
+ err);
+
+   innolux->enabled = false;
+
+   return 0;
+}
+
+static int innolux_panel_unprepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->prepared)
+   return 0;
+
+   err = mipi_dsi_dcs_enter_sleep_mode(innolux->link);
+   if (err < 0) {
+   DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n",
+ err);
+   return err;
+   }
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+
+   /* T8: 80ms - 1000ms */
+   msleep(80);
+
+   err = regulator_disable(innolux->supply);
+   if (err < 0)
+   return err;
+
+   innolux->prepared = false;
+
+   return 0;
+}
+
+static int innolux_panel_prepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err, regulator_err;
+
+   if (innolux->prepared)
+   return 0;
+
+   gpiod_set_value_cansleep(inn

[PATCH v4 2/2] drm/panel: add innolux,p079zca panel driver

2017-03-23 Thread Chris Zhong
Support Innolux P079ZCA 7.85" 768x1024 TFT LCD panel, it is a MIPI DSI
panel.

Signed-off-by: Chris Zhong 
Reviewed-by: Sean Paul 
Tested-by: Brian Norris 
---

Changes in v4:
- remove backlight check after probe
- add bpc info

Changes in v3:
- printk err after regulator_disable(innolux->supply)

Changes in v2:
- add some error check
- always use Low power mode to send commend
- add comments for all the sleep
- use DRM_DEV_ERROR instead of dev_err

 drivers/gpu/drm/panel/Kconfig |  11 +
 drivers/gpu/drm/panel/Makefile|   1 +
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 340 ++
 3 files changed, 352 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-innolux-p079zca.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 62aba97..99dd010 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -18,6 +18,17 @@ config DRM_PANEL_SIMPLE
  that it can be automatically turned off when the panel goes into a
  low power state.
 
+config DRM_PANEL_INNOLUX_P079ZCA
+   tristate "Innolux P079ZCA panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   depends on BACKLIGHT_CLASS_DEVICE
+   help
+ Say Y here if you want to enable support for Innolux P079ZCA
+ TFT-LCD modules. The panel has a 1024x768 resolution and uses
+ 24 bit RGB per pixel. It provides a MIPI DSI interface to
+ the host and has a built-in LED backlight.
+
 config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index a5c7ec0..bda2aa4 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
+obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
 obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
new file mode 100644
index 000..6ba9344
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct innolux_panel {
+   struct drm_panel base;
+   struct mipi_dsi_device *link;
+
+   struct backlight_device *backlight;
+   struct regulator *supply;
+   struct gpio_desc *enable_gpio;
+
+   bool prepared;
+   bool enabled;
+};
+
+static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel)
+{
+   return container_of(panel, struct innolux_panel, base);
+}
+
+static int innolux_panel_disable(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->enabled)
+   return 0;
+
+   innolux->backlight->props.power = FB_BLANK_POWERDOWN;
+   backlight_update_status(innolux->backlight);
+
+   err = mipi_dsi_dcs_set_display_off(innolux->link);
+   if (err < 0)
+   DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n",
+ err);
+
+   innolux->enabled = false;
+
+   return 0;
+}
+
+static int innolux_panel_unprepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->prepared)
+   return 0;
+
+   err = mipi_dsi_dcs_enter_sleep_mode(innolux->link);
+   if (err < 0) {
+   DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n",
+ err);
+   return err;
+   }
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+
+   /* T8: 80ms - 1000ms */
+   msleep(80);
+
+   err = regulator_disable(innolux->supply);
+   if (err < 0)
+   return err;
+
+   innolux->prepared = false;
+
+   return 0;
+}
+
+static int innolux_panel_prepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err, regulator_err;
+
+   if (innolux->prepared)
+   return 0;
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+
+   err = regulator_enable(innolux->supply);
+   

[PATCH v4 1/2] dt-bindings: Add INNOLUX P079ZCA panel bindings

2017-03-23 Thread Chris Zhong
The Innolux P079ZCA is a 7.85" panel with a 768X1024 resolution and
connected to DSI using four lanes.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Reviewed-by: Brian Norris <briannor...@chromium.org>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 .../bindings/display/panel/innolux,p079zca.txt | 23 ++
 1 file changed, 23 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt

diff --git 
a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt 
b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
new file mode 100644
index 000..5c70a83
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
@@ -0,0 +1,23 @@
+Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,p079zca"
+- reg: DSI virtual channel of the peripheral
+- power-supply: phandle of the regulator that provides the supply voltage
+- enable-gpios: panel enable gpio
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+   _dsi {
+   panel {
+   compatible = "innolux,p079zca";
+   reg = <0>;
+   power-supply = <...>;
+   backlight = <>;
+   enable-gpios = < 13 GPIO_ACTIVE_HIGH>;
+   status = "okay";
+   };
+   };
-- 
2.6.3



[PATCH v4 1/2] dt-bindings: Add INNOLUX P079ZCA panel bindings

2017-03-23 Thread Chris Zhong
The Innolux P079ZCA is a 7.85" panel with a 768X1024 resolution and
connected to DSI using four lanes.

Signed-off-by: Chris Zhong 
Reviewed-by: Brian Norris 
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 .../bindings/display/panel/innolux,p079zca.txt | 23 ++
 1 file changed, 23 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt

diff --git 
a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt 
b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
new file mode 100644
index 000..5c70a83
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
@@ -0,0 +1,23 @@
+Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,p079zca"
+- reg: DSI virtual channel of the peripheral
+- power-supply: phandle of the regulator that provides the supply voltage
+- enable-gpios: panel enable gpio
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+   _dsi {
+   panel {
+   compatible = "innolux,p079zca";
+   reg = <0>;
+   power-supply = <...>;
+   backlight = <>;
+   enable-gpios = < 13 GPIO_ACTIVE_HIGH>;
+   status = "okay";
+   };
+   };
-- 
2.6.3



[PATCH v4 2/4] dt-bindings: add the grf clock for dw-mipi-dsi

2017-03-21 Thread Chris Zhong
For RK3399, the grf clock should be controlled by dw-mipi-dsi driver,
add the description for this clock.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
---

Changes in v4:
- remove "additional"

Changes in v3: None
Changes in v2: None

 .../devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
index 188f6f7..1d722f5 100644
--- 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
+++ 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
@@ -10,7 +10,7 @@ Required properties:
 - interrupts: Represent the controller's interrupt to the CPU(s).
 - clocks, clock-names: Phandles to the controller's pll reference
   clock(ref) and APB clock(pclk). For RK3399, a phy config clock
-  (phy_cfg) is additional required. As described in [1].
+  (phy_cfg) and a grf clock(grf) are required. As described in [1].
 - rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
 - ports: contain a port node with endpoint definitions as defined in [2].
   For vopb,set the reg = <0> and set the reg = <1> for vopl.
-- 
2.6.3



[PATCH v4 2/4] dt-bindings: add the grf clock for dw-mipi-dsi

2017-03-21 Thread Chris Zhong
For RK3399, the grf clock should be controlled by dw-mipi-dsi driver,
add the description for this clock.

Signed-off-by: Chris Zhong 
Reviewed-by: Sean Paul 
---

Changes in v4:
- remove "additional"

Changes in v3: None
Changes in v2: None

 .../devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
index 188f6f7..1d722f5 100644
--- 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
+++ 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
@@ -10,7 +10,7 @@ Required properties:
 - interrupts: Represent the controller's interrupt to the CPU(s).
 - clocks, clock-names: Phandles to the controller's pll reference
   clock(ref) and APB clock(pclk). For RK3399, a phy config clock
-  (phy_cfg) is additional required. As described in [1].
+  (phy_cfg) and a grf clock(grf) are required. As described in [1].
 - rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
 - ports: contain a port node with endpoint definitions as defined in [2].
   For vopb,set the reg = <0> and set the reg = <1> for vopl.
-- 
2.6.3



[PATCH v4 3/4] drm/rockchip/dsi: enable the grf clk before writing grf registers

2017-03-21 Thread Chris Zhong
For RK3399, the grf clk should be enabled before writing grf registers,
otherwise the register value can not be changed.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
---

Changes in v4:
- print the err after clk_prepare_enable(dsi->grf_clk)

Changes in v3:
- add a DW_MIPI_NEEDS_GRF_CLK for RK3399

Changes in v2:
- check the grf_clk only for RK3399

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 26 +-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 68f48b0..dc8fd22 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -252,6 +252,7 @@
 #define THS_ZERO_PROGRAM_ENBIT(6)
 
 #define DW_MIPI_NEEDS_PHY_CFG_CLK  BIT(0)
+#define DW_MIPI_NEEDS_GRF_CLK  BIT(1)
 
 enum {
BANDGAP_97_07,
@@ -294,6 +295,7 @@ struct dw_mipi_dsi {
struct regmap *grf_regmap;
void __iomem *base;
 
+   struct clk *grf_clk;
struct clk *pllref_clk;
struct clk *pclk;
struct clk *phy_cfg_clk;
@@ -982,6 +984,17 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
dw_mipi_dsi_dphy_interface_config(dsi);
dw_mipi_dsi_clear_err(dsi);
 
+   /*
+* For the RK3399, the clk of grf must be enabled before writing grf
+* register. And for RK3288 or other soc, this grf_clk must be NULL,
+* the clk_prepare_enable return true directly.
+*/
+   ret = clk_prepare_enable(dsi->grf_clk);
+   if (ret) {
+   dev_err(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
+   return;
+   }
+
if (pdata->grf_dsi0_mode_reg)
regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
 pdata->grf_dsi0_mode);
@@ -1006,6 +1019,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val);
dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
dsi->dpms_mode = DRM_MODE_DPMS_ON;
+
+   clk_disable_unprepare(dsi->grf_clk);
 }
 
 static int
@@ -1139,7 +1154,7 @@ static struct dw_mipi_dsi_plat_data 
rk3399_mipi_dsi_drv_data = {
.grf_switch_reg = RK3399_GRF_SOC_CON19,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
-   .flags = DW_MIPI_NEEDS_PHY_CFG_CLK,
+   .flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
.max_data_lanes = 4,
 };
 
@@ -1240,6 +1255,15 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
}
}
 
+   if (pdata->flags & DW_MIPI_NEEDS_GRF_CLK) {
+   dsi->grf_clk = devm_clk_get(dev, "grf");
+   if (IS_ERR(dsi->grf_clk)) {
+   ret = PTR_ERR(dsi->grf_clk);
+   dev_err(dev, "Unable to get grf_clk: %d\n", ret);
+   return ret;
+   }
+   }
+
ret = clk_prepare_enable(dsi->pllref_clk);
if (ret) {
dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);
-- 
2.6.3



[PATCH v4 3/4] drm/rockchip/dsi: enable the grf clk before writing grf registers

2017-03-21 Thread Chris Zhong
For RK3399, the grf clk should be enabled before writing grf registers,
otherwise the register value can not be changed.

Signed-off-by: Chris Zhong 
Reviewed-by: Sean Paul 
---

Changes in v4:
- print the err after clk_prepare_enable(dsi->grf_clk)

Changes in v3:
- add a DW_MIPI_NEEDS_GRF_CLK for RK3399

Changes in v2:
- check the grf_clk only for RK3399

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 26 +-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 68f48b0..dc8fd22 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -252,6 +252,7 @@
 #define THS_ZERO_PROGRAM_ENBIT(6)
 
 #define DW_MIPI_NEEDS_PHY_CFG_CLK  BIT(0)
+#define DW_MIPI_NEEDS_GRF_CLK  BIT(1)
 
 enum {
BANDGAP_97_07,
@@ -294,6 +295,7 @@ struct dw_mipi_dsi {
struct regmap *grf_regmap;
void __iomem *base;
 
+   struct clk *grf_clk;
struct clk *pllref_clk;
struct clk *pclk;
struct clk *phy_cfg_clk;
@@ -982,6 +984,17 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
dw_mipi_dsi_dphy_interface_config(dsi);
dw_mipi_dsi_clear_err(dsi);
 
+   /*
+* For the RK3399, the clk of grf must be enabled before writing grf
+* register. And for RK3288 or other soc, this grf_clk must be NULL,
+* the clk_prepare_enable return true directly.
+*/
+   ret = clk_prepare_enable(dsi->grf_clk);
+   if (ret) {
+   dev_err(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
+   return;
+   }
+
if (pdata->grf_dsi0_mode_reg)
regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
 pdata->grf_dsi0_mode);
@@ -1006,6 +1019,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val);
dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
dsi->dpms_mode = DRM_MODE_DPMS_ON;
+
+   clk_disable_unprepare(dsi->grf_clk);
 }
 
 static int
@@ -1139,7 +1154,7 @@ static struct dw_mipi_dsi_plat_data 
rk3399_mipi_dsi_drv_data = {
.grf_switch_reg = RK3399_GRF_SOC_CON19,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
-   .flags = DW_MIPI_NEEDS_PHY_CFG_CLK,
+   .flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
.max_data_lanes = 4,
 };
 
@@ -1240,6 +1255,15 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
}
}
 
+   if (pdata->flags & DW_MIPI_NEEDS_GRF_CLK) {
+   dsi->grf_clk = devm_clk_get(dev, "grf");
+   if (IS_ERR(dsi->grf_clk)) {
+   ret = PTR_ERR(dsi->grf_clk);
+   dev_err(dev, "Unable to get grf_clk: %d\n", ret);
+   return ret;
+   }
+   }
+
ret = clk_prepare_enable(dsi->pllref_clk);
if (ret) {
dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);
-- 
2.6.3



[PATCH v4 1/4] drm/rockchip/dsi: check phy_cfg_clk only for RK3399

2017-03-21 Thread Chris Zhong
For RK3399, the phy_cfg_clk is a required clock, if phy_cfg_clk is
disabled, MIPI phy can not work. Let's return a error if there is no
phy_cfg_clk in dts property, when the pdata match RK3399.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
---

Changes in v4: None
Changes in v3:
- add a DW_MIPI_NEEDS_PHY_CFG_CLK for RK3399

Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index f84f9ae..68f48b0 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -251,6 +251,8 @@
 #define THS_PRE_PROGRAM_EN BIT(7)
 #define THS_ZERO_PROGRAM_ENBIT(6)
 
+#define DW_MIPI_NEEDS_PHY_CFG_CLK  BIT(0)
+
 enum {
BANDGAP_97_07,
BANDGAP_98_05,
@@ -279,6 +281,7 @@ struct dw_mipi_dsi_plat_data {
u32 grf_switch_reg;
u32 grf_dsi0_mode;
u32 grf_dsi0_mode_reg;
+   unsigned int flags;
unsigned int max_data_lanes;
 };
 
@@ -1136,6 +1139,7 @@ static struct dw_mipi_dsi_plat_data 
rk3399_mipi_dsi_drv_data = {
.grf_switch_reg = RK3399_GRF_SOC_CON19,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
+   .flags = DW_MIPI_NEEDS_PHY_CFG_CLK,
.max_data_lanes = 4,
 };
 
@@ -1227,15 +1231,13 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
clk_disable_unprepare(dsi->pclk);
}
 
-   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
-   if (IS_ERR(dsi->phy_cfg_clk)) {
-   ret = PTR_ERR(dsi->phy_cfg_clk);
-   if (ret != -ENOENT) {
+   if (pdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) {
+   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
+   if (IS_ERR(dsi->phy_cfg_clk)) {
+   ret = PTR_ERR(dsi->phy_cfg_clk);
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
-   dsi->phy_cfg_clk = NULL;
-   dev_dbg(dev, "have not phy_cfg_clk\n");
}
 
ret = clk_prepare_enable(dsi->pllref_clk);
-- 
2.6.3



[PATCH v4 4/4] drm/rockchip/dsi: correct the grf_switch_reg name

2017-03-21 Thread Chris Zhong
For the RK3399, the grf_switch_reg name should be RK3399_GRF_SOC_CON20,
not RK3399_GRF_SOC_CON19.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Reviewed-by: Brian Norris <briannor...@chromium.org>
Reviewed-by: Sean Paul <seanp...@chromium.org>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index dc8fd22..3aedcba 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -34,7 +34,7 @@
 #define RK3288_DSI0_SEL_VOP_LITBIT(6)
 #define RK3288_DSI1_SEL_VOP_LITBIT(9)
 
-#define RK3399_GRF_SOC_CON19   0x6250
+#define RK3399_GRF_SOC_CON20   0x6250
 #define RK3399_DSI0_SEL_VOP_LITBIT(0)
 #define RK3399_DSI1_SEL_VOP_LITBIT(4)
 
@@ -1151,7 +1151,7 @@ static struct dw_mipi_dsi_plat_data 
rk3288_mipi_dsi_drv_data = {
 static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = {
.dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT,
.dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT,
-   .grf_switch_reg = RK3399_GRF_SOC_CON19,
+   .grf_switch_reg = RK3399_GRF_SOC_CON20,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
.flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
-- 
2.6.3



[PATCH v4 1/4] drm/rockchip/dsi: check phy_cfg_clk only for RK3399

2017-03-21 Thread Chris Zhong
For RK3399, the phy_cfg_clk is a required clock, if phy_cfg_clk is
disabled, MIPI phy can not work. Let's return a error if there is no
phy_cfg_clk in dts property, when the pdata match RK3399.

Signed-off-by: Chris Zhong 
Reviewed-by: Sean Paul 
---

Changes in v4: None
Changes in v3:
- add a DW_MIPI_NEEDS_PHY_CFG_CLK for RK3399

Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index f84f9ae..68f48b0 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -251,6 +251,8 @@
 #define THS_PRE_PROGRAM_EN BIT(7)
 #define THS_ZERO_PROGRAM_ENBIT(6)
 
+#define DW_MIPI_NEEDS_PHY_CFG_CLK  BIT(0)
+
 enum {
BANDGAP_97_07,
BANDGAP_98_05,
@@ -279,6 +281,7 @@ struct dw_mipi_dsi_plat_data {
u32 grf_switch_reg;
u32 grf_dsi0_mode;
u32 grf_dsi0_mode_reg;
+   unsigned int flags;
unsigned int max_data_lanes;
 };
 
@@ -1136,6 +1139,7 @@ static struct dw_mipi_dsi_plat_data 
rk3399_mipi_dsi_drv_data = {
.grf_switch_reg = RK3399_GRF_SOC_CON19,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
+   .flags = DW_MIPI_NEEDS_PHY_CFG_CLK,
.max_data_lanes = 4,
 };
 
@@ -1227,15 +1231,13 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
clk_disable_unprepare(dsi->pclk);
}
 
-   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
-   if (IS_ERR(dsi->phy_cfg_clk)) {
-   ret = PTR_ERR(dsi->phy_cfg_clk);
-   if (ret != -ENOENT) {
+   if (pdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) {
+   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
+   if (IS_ERR(dsi->phy_cfg_clk)) {
+   ret = PTR_ERR(dsi->phy_cfg_clk);
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
-   dsi->phy_cfg_clk = NULL;
-   dev_dbg(dev, "have not phy_cfg_clk\n");
}
 
ret = clk_prepare_enable(dsi->pllref_clk);
-- 
2.6.3



[PATCH v4 4/4] drm/rockchip/dsi: correct the grf_switch_reg name

2017-03-21 Thread Chris Zhong
For the RK3399, the grf_switch_reg name should be RK3399_GRF_SOC_CON20,
not RK3399_GRF_SOC_CON19.

Signed-off-by: Chris Zhong 
Reviewed-by: Brian Norris 
Reviewed-by: Sean Paul 
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index dc8fd22..3aedcba 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -34,7 +34,7 @@
 #define RK3288_DSI0_SEL_VOP_LITBIT(6)
 #define RK3288_DSI1_SEL_VOP_LITBIT(9)
 
-#define RK3399_GRF_SOC_CON19   0x6250
+#define RK3399_GRF_SOC_CON20   0x6250
 #define RK3399_DSI0_SEL_VOP_LITBIT(0)
 #define RK3399_DSI1_SEL_VOP_LITBIT(4)
 
@@ -1151,7 +1151,7 @@ static struct dw_mipi_dsi_plat_data 
rk3288_mipi_dsi_drv_data = {
 static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = {
.dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT,
.dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT,
-   .grf_switch_reg = RK3399_GRF_SOC_CON19,
+   .grf_switch_reg = RK3399_GRF_SOC_CON20,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
.flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
-- 
2.6.3



[PATCH v4 0/4] RK3399 dw-mipi-dsi patches

2017-03-21 Thread Chris Zhong
Hi all

This series set the phy_cfg_clk to be a required clock for RK3399, and
add a grf clock control in dw-mipi-dsi driver. And then correct a
register name.


Changes in v4:
- remove "additional"
- print the err after clk_prepare_enable(dsi->grf_clk)

Changes in v3:
- add a DW_MIPI_NEEDS_PHY_CFG_CLK for RK3399
- add a DW_MIPI_NEEDS_GRF_CLK for RK3399

Changes in v2:
- check the grf_clk only for RK3399

Chris Zhong (4):
  drm/rockchip/dsi: check phy_cfg_clk only for RK3399
  dt-bindings: add the grf clock for dw-mipi-dsi
  drm/rockchip/dsi: enable the grf clk before writing grf registers
  drm/rockchip/dsi: correct the grf_switch_reg name

 .../display/rockchip/dw_mipi_dsi_rockchip.txt  |  2 +-
 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 42 +-
 2 files changed, 35 insertions(+), 9 deletions(-)

-- 
2.6.3



[PATCH v4 0/4] RK3399 dw-mipi-dsi patches

2017-03-21 Thread Chris Zhong
Hi all

This series set the phy_cfg_clk to be a required clock for RK3399, and
add a grf clock control in dw-mipi-dsi driver. And then correct a
register name.


Changes in v4:
- remove "additional"
- print the err after clk_prepare_enable(dsi->grf_clk)

Changes in v3:
- add a DW_MIPI_NEEDS_PHY_CFG_CLK for RK3399
- add a DW_MIPI_NEEDS_GRF_CLK for RK3399

Changes in v2:
- check the grf_clk only for RK3399

Chris Zhong (4):
  drm/rockchip/dsi: check phy_cfg_clk only for RK3399
  dt-bindings: add the grf clock for dw-mipi-dsi
  drm/rockchip/dsi: enable the grf clk before writing grf registers
  drm/rockchip/dsi: correct the grf_switch_reg name

 .../display/rockchip/dw_mipi_dsi_rockchip.txt  |  2 +-
 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 42 +-
 2 files changed, 35 insertions(+), 9 deletions(-)

-- 
2.6.3



[PATCH v3 1/2] dt-bindings: Add INNOLUX P079ZCA panel bindings

2017-03-21 Thread Chris Zhong
The Innolux P079ZCA is a 7.85" panel with a 768X1024 resolution and
connected to DSI using four lanes.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Reviewed-by: Brian Norris <briannor...@chromium.org>
---

Changes in v3: None
Changes in v2: None

 .../bindings/display/panel/innolux,p079zca.txt | 23 ++
 1 file changed, 23 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt

diff --git 
a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt 
b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
new file mode 100644
index 000..5c70a83
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
@@ -0,0 +1,23 @@
+Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,p079zca"
+- reg: DSI virtual channel of the peripheral
+- power-supply: phandle of the regulator that provides the supply voltage
+- enable-gpios: panel enable gpio
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+   _dsi {
+   panel {
+   compatible = "innolux,p079zca";
+   reg = <0>;
+   power-supply = <...>;
+   backlight = <>;
+   enable-gpios = < 13 GPIO_ACTIVE_HIGH>;
+   status = "okay";
+   };
+   };
-- 
2.6.3



[PATCH v3 1/2] dt-bindings: Add INNOLUX P079ZCA panel bindings

2017-03-21 Thread Chris Zhong
The Innolux P079ZCA is a 7.85" panel with a 768X1024 resolution and
connected to DSI using four lanes.

Signed-off-by: Chris Zhong 
Reviewed-by: Brian Norris 
---

Changes in v3: None
Changes in v2: None

 .../bindings/display/panel/innolux,p079zca.txt | 23 ++
 1 file changed, 23 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt

diff --git 
a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt 
b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
new file mode 100644
index 000..5c70a83
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
@@ -0,0 +1,23 @@
+Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,p079zca"
+- reg: DSI virtual channel of the peripheral
+- power-supply: phandle of the regulator that provides the supply voltage
+- enable-gpios: panel enable gpio
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+   _dsi {
+   panel {
+   compatible = "innolux,p079zca";
+   reg = <0>;
+   power-supply = <...>;
+   backlight = <>;
+   enable-gpios = < 13 GPIO_ACTIVE_HIGH>;
+   status = "okay";
+   };
+   };
-- 
2.6.3



[PATCH v3 2/2] drm/panel: add innolux,p079zca panel driver

2017-03-21 Thread Chris Zhong
Support Innolux P079ZCA 7.85" 768x1024 TFT LCD panel, it is a MIPI DSI
panel.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
Tested-by: Brian Norris <briannor...@chromium.org>
---

Changes in v3:
- printk err after regulator_disable(innolux->supply)

Changes in v2:
- add some error check
- always use Low power mode to send commend
- add comments for all the sleep
- use DRM_DEV_ERROR instead of dev_err

 drivers/gpu/drm/panel/Kconfig |  11 +
 drivers/gpu/drm/panel/Makefile|   1 +
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 345 ++
 3 files changed, 357 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-innolux-p079zca.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 62aba97..99dd010 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -18,6 +18,17 @@ config DRM_PANEL_SIMPLE
  that it can be automatically turned off when the panel goes into a
  low power state.
 
+config DRM_PANEL_INNOLUX_P079ZCA
+   tristate "Innolux P079ZCA panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   depends on BACKLIGHT_CLASS_DEVICE
+   help
+ Say Y here if you want to enable support for Innolux P079ZCA
+ TFT-LCD modules. The panel has a 1024x768 resolution and uses
+ 24 bit RGB per pixel. It provides a MIPI DSI interface to
+ the host and has a built-in LED backlight.
+
 config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index a5c7ec0..bda2aa4 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
+obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
 obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
new file mode 100644
index 000..9f3423a0
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct innolux_panel {
+   struct drm_panel base;
+   struct mipi_dsi_device *link;
+
+   struct backlight_device *backlight;
+   struct regulator *supply;
+   struct gpio_desc *enable_gpio;
+
+   bool prepared;
+   bool enabled;
+};
+
+static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel)
+{
+   return container_of(panel, struct innolux_panel, base);
+}
+
+static int innolux_panel_disable(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->enabled)
+   return 0;
+
+   if (innolux->backlight) {
+   innolux->backlight->props.power = FB_BLANK_POWERDOWN;
+   backlight_update_status(innolux->backlight);
+   }
+
+   err = mipi_dsi_dcs_set_display_off(innolux->link);
+   if (err < 0)
+   DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n",
+ err);
+
+   innolux->enabled = false;
+
+   return 0;
+}
+
+static int innolux_panel_unprepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->prepared)
+   return 0;
+
+   err = mipi_dsi_dcs_enter_sleep_mode(innolux->link);
+   if (err < 0) {
+   DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n",
+ err);
+   return err;
+   }
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+
+   /* T8: 80ms - 1000ms */
+   msleep(80);
+
+   err = regulator_disable(innolux->supply);
+   if (err < 0)
+   return err;
+
+   innolux->prepared = false;
+
+   return 0;
+}
+
+static int innolux_panel_prepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err, regulator_err;
+
+   if (innolux->prepared)
+   return 0;
+
+   gpiod_set_value_cansleep(inno

[PATCH v3 2/2] drm/panel: add innolux,p079zca panel driver

2017-03-21 Thread Chris Zhong
Support Innolux P079ZCA 7.85" 768x1024 TFT LCD panel, it is a MIPI DSI
panel.

Signed-off-by: Chris Zhong 
Reviewed-by: Sean Paul 
Tested-by: Brian Norris 
---

Changes in v3:
- printk err after regulator_disable(innolux->supply)

Changes in v2:
- add some error check
- always use Low power mode to send commend
- add comments for all the sleep
- use DRM_DEV_ERROR instead of dev_err

 drivers/gpu/drm/panel/Kconfig |  11 +
 drivers/gpu/drm/panel/Makefile|   1 +
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 345 ++
 3 files changed, 357 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-innolux-p079zca.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 62aba97..99dd010 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -18,6 +18,17 @@ config DRM_PANEL_SIMPLE
  that it can be automatically turned off when the panel goes into a
  low power state.
 
+config DRM_PANEL_INNOLUX_P079ZCA
+   tristate "Innolux P079ZCA panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   depends on BACKLIGHT_CLASS_DEVICE
+   help
+ Say Y here if you want to enable support for Innolux P079ZCA
+ TFT-LCD modules. The panel has a 1024x768 resolution and uses
+ 24 bit RGB per pixel. It provides a MIPI DSI interface to
+ the host and has a built-in LED backlight.
+
 config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index a5c7ec0..bda2aa4 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
+obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
 obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
new file mode 100644
index 000..9f3423a0
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct innolux_panel {
+   struct drm_panel base;
+   struct mipi_dsi_device *link;
+
+   struct backlight_device *backlight;
+   struct regulator *supply;
+   struct gpio_desc *enable_gpio;
+
+   bool prepared;
+   bool enabled;
+};
+
+static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel)
+{
+   return container_of(panel, struct innolux_panel, base);
+}
+
+static int innolux_panel_disable(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->enabled)
+   return 0;
+
+   if (innolux->backlight) {
+   innolux->backlight->props.power = FB_BLANK_POWERDOWN;
+   backlight_update_status(innolux->backlight);
+   }
+
+   err = mipi_dsi_dcs_set_display_off(innolux->link);
+   if (err < 0)
+   DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n",
+ err);
+
+   innolux->enabled = false;
+
+   return 0;
+}
+
+static int innolux_panel_unprepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->prepared)
+   return 0;
+
+   err = mipi_dsi_dcs_enter_sleep_mode(innolux->link);
+   if (err < 0) {
+   DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n",
+ err);
+   return err;
+   }
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+
+   /* T8: 80ms - 1000ms */
+   msleep(80);
+
+   err = regulator_disable(innolux->supply);
+   if (err < 0)
+   return err;
+
+   innolux->prepared = false;
+
+   return 0;
+}
+
+static int innolux_panel_prepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err, regulator_err;
+
+   if (innolux->prepared)
+   return 0;
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+
+   err = regulator_enable(innolux->supply);
+   

[PATCH v3 1/4] drm/rockchip/dsi: check phy_cfg_clk only for RK3399

2017-03-16 Thread Chris Zhong
For RK3399, the phy_cfg_clk is a required clock, if phy_cfg_clk is
disabled, MIPI phy can not work. Let's return a error if there is no
phy_cfg_clk in dts property, when the pdata match RK3399.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v3:
- add a DW_MIPI_NEEDS_PHY_CFG_CLK for RK3399

Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index f84f9ae..68f48b0 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -251,6 +251,8 @@
 #define THS_PRE_PROGRAM_EN BIT(7)
 #define THS_ZERO_PROGRAM_ENBIT(6)
 
+#define DW_MIPI_NEEDS_PHY_CFG_CLK  BIT(0)
+
 enum {
BANDGAP_97_07,
BANDGAP_98_05,
@@ -279,6 +281,7 @@ struct dw_mipi_dsi_plat_data {
u32 grf_switch_reg;
u32 grf_dsi0_mode;
u32 grf_dsi0_mode_reg;
+   unsigned int flags;
unsigned int max_data_lanes;
 };
 
@@ -1136,6 +1139,7 @@ static struct dw_mipi_dsi_plat_data 
rk3399_mipi_dsi_drv_data = {
.grf_switch_reg = RK3399_GRF_SOC_CON19,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
+   .flags = DW_MIPI_NEEDS_PHY_CFG_CLK,
.max_data_lanes = 4,
 };
 
@@ -1227,15 +1231,13 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
clk_disable_unprepare(dsi->pclk);
}
 
-   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
-   if (IS_ERR(dsi->phy_cfg_clk)) {
-   ret = PTR_ERR(dsi->phy_cfg_clk);
-   if (ret != -ENOENT) {
+   if (pdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) {
+   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
+   if (IS_ERR(dsi->phy_cfg_clk)) {
+   ret = PTR_ERR(dsi->phy_cfg_clk);
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
-   dsi->phy_cfg_clk = NULL;
-   dev_dbg(dev, "have not phy_cfg_clk\n");
}
 
ret = clk_prepare_enable(dsi->pllref_clk);
-- 
2.6.3



[PATCH v3 1/4] drm/rockchip/dsi: check phy_cfg_clk only for RK3399

2017-03-16 Thread Chris Zhong
For RK3399, the phy_cfg_clk is a required clock, if phy_cfg_clk is
disabled, MIPI phy can not work. Let's return a error if there is no
phy_cfg_clk in dts property, when the pdata match RK3399.

Signed-off-by: Chris Zhong 
---

Changes in v3:
- add a DW_MIPI_NEEDS_PHY_CFG_CLK for RK3399

Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index f84f9ae..68f48b0 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -251,6 +251,8 @@
 #define THS_PRE_PROGRAM_EN BIT(7)
 #define THS_ZERO_PROGRAM_ENBIT(6)
 
+#define DW_MIPI_NEEDS_PHY_CFG_CLK  BIT(0)
+
 enum {
BANDGAP_97_07,
BANDGAP_98_05,
@@ -279,6 +281,7 @@ struct dw_mipi_dsi_plat_data {
u32 grf_switch_reg;
u32 grf_dsi0_mode;
u32 grf_dsi0_mode_reg;
+   unsigned int flags;
unsigned int max_data_lanes;
 };
 
@@ -1136,6 +1139,7 @@ static struct dw_mipi_dsi_plat_data 
rk3399_mipi_dsi_drv_data = {
.grf_switch_reg = RK3399_GRF_SOC_CON19,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
+   .flags = DW_MIPI_NEEDS_PHY_CFG_CLK,
.max_data_lanes = 4,
 };
 
@@ -1227,15 +1231,13 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
clk_disable_unprepare(dsi->pclk);
}
 
-   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
-   if (IS_ERR(dsi->phy_cfg_clk)) {
-   ret = PTR_ERR(dsi->phy_cfg_clk);
-   if (ret != -ENOENT) {
+   if (pdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) {
+   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
+   if (IS_ERR(dsi->phy_cfg_clk)) {
+   ret = PTR_ERR(dsi->phy_cfg_clk);
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
-   dsi->phy_cfg_clk = NULL;
-   dev_dbg(dev, "have not phy_cfg_clk\n");
}
 
ret = clk_prepare_enable(dsi->pllref_clk);
-- 
2.6.3



[PATCH v3 0/4] RK3399 dw-mipi-dsi patches

2017-03-16 Thread Chris Zhong
Hi all

This series set the phy_cfg_clk to be a required clock for RK3399, and
add a grf clock control in dw-mipi-dsi driver. And then correct a
register name.


Changes in v3:
- add a DW_MIPI_NEEDS_PHY_CFG_CLK for RK3399
- add a DW_MIPI_NEEDS_GRF_CLK for RK3399

Changes in v2:
- check the grf_clk only for RK3399

Chris Zhong (4):
  drm/rockchip/dsi: check phy_cfg_clk only for RK3399
  dt-bindings: add the grf clock for dw-mipi-dsi
  drm/rockchip/dsi: enable the grf clk before writing grf registers
  drm/rockchip/dsi: correct the grf_switch_reg name

 .../display/rockchip/dw_mipi_dsi_rockchip.txt  |  2 +-
 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 42 +-
 2 files changed, 35 insertions(+), 9 deletions(-)

-- 
2.6.3



[PATCH v3 0/4] RK3399 dw-mipi-dsi patches

2017-03-16 Thread Chris Zhong
Hi all

This series set the phy_cfg_clk to be a required clock for RK3399, and
add a grf clock control in dw-mipi-dsi driver. And then correct a
register name.


Changes in v3:
- add a DW_MIPI_NEEDS_PHY_CFG_CLK for RK3399
- add a DW_MIPI_NEEDS_GRF_CLK for RK3399

Changes in v2:
- check the grf_clk only for RK3399

Chris Zhong (4):
  drm/rockchip/dsi: check phy_cfg_clk only for RK3399
  dt-bindings: add the grf clock for dw-mipi-dsi
  drm/rockchip/dsi: enable the grf clk before writing grf registers
  drm/rockchip/dsi: correct the grf_switch_reg name

 .../display/rockchip/dw_mipi_dsi_rockchip.txt  |  2 +-
 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 42 +-
 2 files changed, 35 insertions(+), 9 deletions(-)

-- 
2.6.3



[PATCH v3 3/4] drm/rockchip/dsi: enable the grf clk before writing grf registers

2017-03-16 Thread Chris Zhong
For RK3399, the grf clk should be enabled before writing grf registers,
otherwise the register value can not be changed.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v3:
- add a DW_MIPI_NEEDS_GRF_CLK for RK3399

Changes in v2:
- check the grf_clk only for RK3399

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 26 +-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 68f48b0..5a18281 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -252,6 +252,7 @@
 #define THS_ZERO_PROGRAM_ENBIT(6)
 
 #define DW_MIPI_NEEDS_PHY_CFG_CLK  BIT(0)
+#define DW_MIPI_NEEDS_GRF_CLK  BIT(1)
 
 enum {
BANDGAP_97_07,
@@ -294,6 +295,7 @@ struct dw_mipi_dsi {
struct regmap *grf_regmap;
void __iomem *base;
 
+   struct clk *grf_clk;
struct clk *pllref_clk;
struct clk *pclk;
struct clk *phy_cfg_clk;
@@ -982,6 +984,17 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
dw_mipi_dsi_dphy_interface_config(dsi);
dw_mipi_dsi_clear_err(dsi);
 
+   /*
+* For the RK3399, the clk of grf must be enabled before writing grf
+* register. And for RK3288 or other soc, this grf_clk must be NULL,
+* the clk_prepare_enable return true directly.
+*/
+   ret = clk_prepare_enable(dsi->grf_clk);
+   if (ret) {
+   dev_err(dsi->dev, "Failed to enable grf_clk\n");
+   return;
+   }
+
if (pdata->grf_dsi0_mode_reg)
regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
 pdata->grf_dsi0_mode);
@@ -1006,6 +1019,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val);
dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
dsi->dpms_mode = DRM_MODE_DPMS_ON;
+
+   clk_disable_unprepare(dsi->grf_clk);
 }
 
 static int
@@ -1139,7 +1154,7 @@ static struct dw_mipi_dsi_plat_data 
rk3399_mipi_dsi_drv_data = {
.grf_switch_reg = RK3399_GRF_SOC_CON19,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
-   .flags = DW_MIPI_NEEDS_PHY_CFG_CLK,
+   .flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
.max_data_lanes = 4,
 };
 
@@ -1240,6 +1255,15 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
}
}
 
+   if (pdata->flags & DW_MIPI_NEEDS_GRF_CLK) {
+   dsi->grf_clk = devm_clk_get(dev, "grf");
+   if (IS_ERR(dsi->grf_clk)) {
+   ret = PTR_ERR(dsi->grf_clk);
+   dev_err(dev, "Unable to get grf_clk: %d\n", ret);
+   return ret;
+   }
+   }
+
ret = clk_prepare_enable(dsi->pllref_clk);
if (ret) {
dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);
-- 
2.6.3



[PATCH v3 3/4] drm/rockchip/dsi: enable the grf clk before writing grf registers

2017-03-16 Thread Chris Zhong
For RK3399, the grf clk should be enabled before writing grf registers,
otherwise the register value can not be changed.

Signed-off-by: Chris Zhong 
---

Changes in v3:
- add a DW_MIPI_NEEDS_GRF_CLK for RK3399

Changes in v2:
- check the grf_clk only for RK3399

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 26 +-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 68f48b0..5a18281 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -252,6 +252,7 @@
 #define THS_ZERO_PROGRAM_ENBIT(6)
 
 #define DW_MIPI_NEEDS_PHY_CFG_CLK  BIT(0)
+#define DW_MIPI_NEEDS_GRF_CLK  BIT(1)
 
 enum {
BANDGAP_97_07,
@@ -294,6 +295,7 @@ struct dw_mipi_dsi {
struct regmap *grf_regmap;
void __iomem *base;
 
+   struct clk *grf_clk;
struct clk *pllref_clk;
struct clk *pclk;
struct clk *phy_cfg_clk;
@@ -982,6 +984,17 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
dw_mipi_dsi_dphy_interface_config(dsi);
dw_mipi_dsi_clear_err(dsi);
 
+   /*
+* For the RK3399, the clk of grf must be enabled before writing grf
+* register. And for RK3288 or other soc, this grf_clk must be NULL,
+* the clk_prepare_enable return true directly.
+*/
+   ret = clk_prepare_enable(dsi->grf_clk);
+   if (ret) {
+   dev_err(dsi->dev, "Failed to enable grf_clk\n");
+   return;
+   }
+
if (pdata->grf_dsi0_mode_reg)
regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
 pdata->grf_dsi0_mode);
@@ -1006,6 +1019,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val);
dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
dsi->dpms_mode = DRM_MODE_DPMS_ON;
+
+   clk_disable_unprepare(dsi->grf_clk);
 }
 
 static int
@@ -1139,7 +1154,7 @@ static struct dw_mipi_dsi_plat_data 
rk3399_mipi_dsi_drv_data = {
.grf_switch_reg = RK3399_GRF_SOC_CON19,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
-   .flags = DW_MIPI_NEEDS_PHY_CFG_CLK,
+   .flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
.max_data_lanes = 4,
 };
 
@@ -1240,6 +1255,15 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
}
}
 
+   if (pdata->flags & DW_MIPI_NEEDS_GRF_CLK) {
+   dsi->grf_clk = devm_clk_get(dev, "grf");
+   if (IS_ERR(dsi->grf_clk)) {
+   ret = PTR_ERR(dsi->grf_clk);
+   dev_err(dev, "Unable to get grf_clk: %d\n", ret);
+   return ret;
+   }
+   }
+
ret = clk_prepare_enable(dsi->pllref_clk);
if (ret) {
dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);
-- 
2.6.3



[PATCH v3 2/4] dt-bindings: add the grf clock for dw-mipi-dsi

2017-03-16 Thread Chris Zhong
For RK3399, the grf clock should be controlled by dw-mipi-dsi driver,
add the description for this clock.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v3: None
Changes in v2: None

 .../devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
index 188f6f7..7e17a60 100644
--- 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
+++ 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
@@ -10,7 +10,7 @@ Required properties:
 - interrupts: Represent the controller's interrupt to the CPU(s).
 - clocks, clock-names: Phandles to the controller's pll reference
   clock(ref) and APB clock(pclk). For RK3399, a phy config clock
-  (phy_cfg) is additional required. As described in [1].
+  (phy_cfg) and a grf clock(grf) are additional required. As described in [1].
 - rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
 - ports: contain a port node with endpoint definitions as defined in [2].
   For vopb,set the reg = <0> and set the reg = <1> for vopl.
-- 
2.6.3



[PATCH v3 4/4] drm/rockchip/dsi: correct the grf_switch_reg name

2017-03-16 Thread Chris Zhong
For the RK3399, the grf_switch_reg name should be RK3399_GRF_SOC_CON20,
not RK3399_GRF_SOC_CON19.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 5a18281..19b9208 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -34,7 +34,7 @@
 #define RK3288_DSI0_SEL_VOP_LITBIT(6)
 #define RK3288_DSI1_SEL_VOP_LITBIT(9)
 
-#define RK3399_GRF_SOC_CON19   0x6250
+#define RK3399_GRF_SOC_CON20   0x6250
 #define RK3399_DSI0_SEL_VOP_LITBIT(0)
 #define RK3399_DSI1_SEL_VOP_LITBIT(4)
 
@@ -1151,7 +1151,7 @@ static struct dw_mipi_dsi_plat_data 
rk3288_mipi_dsi_drv_data = {
 static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = {
.dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT,
.dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT,
-   .grf_switch_reg = RK3399_GRF_SOC_CON19,
+   .grf_switch_reg = RK3399_GRF_SOC_CON20,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
.flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
-- 
2.6.3



[PATCH v3 2/4] dt-bindings: add the grf clock for dw-mipi-dsi

2017-03-16 Thread Chris Zhong
For RK3399, the grf clock should be controlled by dw-mipi-dsi driver,
add the description for this clock.

Signed-off-by: Chris Zhong 
---

Changes in v3: None
Changes in v2: None

 .../devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
index 188f6f7..7e17a60 100644
--- 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
+++ 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
@@ -10,7 +10,7 @@ Required properties:
 - interrupts: Represent the controller's interrupt to the CPU(s).
 - clocks, clock-names: Phandles to the controller's pll reference
   clock(ref) and APB clock(pclk). For RK3399, a phy config clock
-  (phy_cfg) is additional required. As described in [1].
+  (phy_cfg) and a grf clock(grf) are additional required. As described in [1].
 - rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
 - ports: contain a port node with endpoint definitions as defined in [2].
   For vopb,set the reg = <0> and set the reg = <1> for vopl.
-- 
2.6.3



[PATCH v3 4/4] drm/rockchip/dsi: correct the grf_switch_reg name

2017-03-16 Thread Chris Zhong
For the RK3399, the grf_switch_reg name should be RK3399_GRF_SOC_CON20,
not RK3399_GRF_SOC_CON19.

Signed-off-by: Chris Zhong 
---

Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 5a18281..19b9208 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -34,7 +34,7 @@
 #define RK3288_DSI0_SEL_VOP_LITBIT(6)
 #define RK3288_DSI1_SEL_VOP_LITBIT(9)
 
-#define RK3399_GRF_SOC_CON19   0x6250
+#define RK3399_GRF_SOC_CON20   0x6250
 #define RK3399_DSI0_SEL_VOP_LITBIT(0)
 #define RK3399_DSI1_SEL_VOP_LITBIT(4)
 
@@ -1151,7 +1151,7 @@ static struct dw_mipi_dsi_plat_data 
rk3288_mipi_dsi_drv_data = {
 static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = {
.dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT,
.dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT,
-   .grf_switch_reg = RK3399_GRF_SOC_CON19,
+   .grf_switch_reg = RK3399_GRF_SOC_CON20,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
.flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
-- 
2.6.3



Re: [PATCH v2 1/4] drm/rockchip/dsi: check phy_cfg_clk only for RK3399

2017-03-16 Thread Chris Zhong

Hi John

On 03/16/2017 06:55 PM, John Keeping wrote:

On Thu, 16 Mar 2017 11:31:44 +0800, Chris Zhong wrote:


For RK3399, the phy_cfg_clk is a required clock, if phy_cfg_clk is
disabled, MIPI phy can not work. Let's return a error if there is no
phy_cfg_clk in dts property, when the pdata match RK3399.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v2: None

  drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 10 --
  1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index f84f9ae..11c4166 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -1227,15 +1227,13 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
clk_disable_unprepare(dsi->pclk);
}
  
-	dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");

-   if (IS_ERR(dsi->phy_cfg_clk)) {
-   ret = PTR_ERR(dsi->phy_cfg_clk);
-   if (ret != -ENOENT) {
+   if (pdata == _mipi_dsi_drv_data) {

This will get messy if the next SOC also needs phy_cfg_clk.  Can we do
something like:

if (pdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) {
...

Thanks, good idea. I think RK3368 mipi-dsi driver is on the way. :)



+   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
+   if (IS_ERR(dsi->phy_cfg_clk)) {
+   ret = PTR_ERR(dsi->phy_cfg_clk);
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
-   dsi->phy_cfg_clk = NULL;
-   dev_dbg(dev, "have not phy_cfg_clk\n");
    }
  
  	ret = clk_prepare_enable(dsi->pllref_clk);





--
Chris Zhong




Re: [PATCH v2 1/4] drm/rockchip/dsi: check phy_cfg_clk only for RK3399

2017-03-16 Thread Chris Zhong

Hi John

On 03/16/2017 06:55 PM, John Keeping wrote:

On Thu, 16 Mar 2017 11:31:44 +0800, Chris Zhong wrote:


For RK3399, the phy_cfg_clk is a required clock, if phy_cfg_clk is
disabled, MIPI phy can not work. Let's return a error if there is no
phy_cfg_clk in dts property, when the pdata match RK3399.

Signed-off-by: Chris Zhong 
---

Changes in v2: None

  drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 10 --
  1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index f84f9ae..11c4166 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -1227,15 +1227,13 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
clk_disable_unprepare(dsi->pclk);
}
  
-	dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");

-   if (IS_ERR(dsi->phy_cfg_clk)) {
-   ret = PTR_ERR(dsi->phy_cfg_clk);
-   if (ret != -ENOENT) {
+   if (pdata == _mipi_dsi_drv_data) {

This will get messy if the next SOC also needs phy_cfg_clk.  Can we do
something like:

if (pdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) {
...

Thanks, good idea. I think RK3368 mipi-dsi driver is on the way. :)



+   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
+   if (IS_ERR(dsi->phy_cfg_clk)) {
+   ret = PTR_ERR(dsi->phy_cfg_clk);
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
-   dsi->phy_cfg_clk = NULL;
-   dev_dbg(dev, "have not phy_cfg_clk\n");
    }
  
  	ret = clk_prepare_enable(dsi->pllref_clk);





--
Chris Zhong




[PATCH v2 3/4] drm/rockchip/dsi: enable the grf clk before writing grf registers

2017-03-15 Thread Chris Zhong
For RK3399, the grf clk should be enabled before writing grf registers,
otherwise the register value can not be changed.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v2:
- check the grf_clk only for RK3399

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 11c4166..a4c74c7 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -291,6 +291,7 @@ struct dw_mipi_dsi {
struct regmap *grf_regmap;
void __iomem *base;
 
+   struct clk *grf_clk;
struct clk *pllref_clk;
struct clk *pclk;
struct clk *phy_cfg_clk;
@@ -979,6 +980,17 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
dw_mipi_dsi_dphy_interface_config(dsi);
dw_mipi_dsi_clear_err(dsi);
 
+   /*
+* For the RK3399, the clk of grf must be enabled before writing grf
+* register. And for RK3288 or other soc, this grf_clk must be NULL,
+* the clk_prepare_enable return true directly.
+*/
+   ret = clk_prepare_enable(dsi->grf_clk);
+   if (ret) {
+   dev_err(dsi->dev, "Failed to enable grf_clk\n");
+   return;
+   }
+
if (pdata->grf_dsi0_mode_reg)
regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
 pdata->grf_dsi0_mode);
@@ -1003,6 +1015,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val);
dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
dsi->dpms_mode = DRM_MODE_DPMS_ON;
+
+   clk_disable_unprepare(dsi->grf_clk);
 }
 
 static int
@@ -1234,6 +1248,13 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
+
+   dsi->grf_clk = devm_clk_get(dev, "grf");
+   if (IS_ERR(dsi->grf_clk)) {
+   ret = PTR_ERR(dsi->grf_clk);
+   dev_err(dev, "Unable to get grf_clk: %d\n", ret);
+   return ret;
+   }
}
 
ret = clk_prepare_enable(dsi->pllref_clk);
-- 
2.6.3



[PATCH v2 3/4] drm/rockchip/dsi: enable the grf clk before writing grf registers

2017-03-15 Thread Chris Zhong
For RK3399, the grf clk should be enabled before writing grf registers,
otherwise the register value can not be changed.

Signed-off-by: Chris Zhong 
---

Changes in v2:
- check the grf_clk only for RK3399

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 11c4166..a4c74c7 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -291,6 +291,7 @@ struct dw_mipi_dsi {
struct regmap *grf_regmap;
void __iomem *base;
 
+   struct clk *grf_clk;
struct clk *pllref_clk;
struct clk *pclk;
struct clk *phy_cfg_clk;
@@ -979,6 +980,17 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
dw_mipi_dsi_dphy_interface_config(dsi);
dw_mipi_dsi_clear_err(dsi);
 
+   /*
+* For the RK3399, the clk of grf must be enabled before writing grf
+* register. And for RK3288 or other soc, this grf_clk must be NULL,
+* the clk_prepare_enable return true directly.
+*/
+   ret = clk_prepare_enable(dsi->grf_clk);
+   if (ret) {
+   dev_err(dsi->dev, "Failed to enable grf_clk\n");
+   return;
+   }
+
if (pdata->grf_dsi0_mode_reg)
regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
 pdata->grf_dsi0_mode);
@@ -1003,6 +1015,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val);
dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
dsi->dpms_mode = DRM_MODE_DPMS_ON;
+
+   clk_disable_unprepare(dsi->grf_clk);
 }
 
 static int
@@ -1234,6 +1248,13 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
+
+   dsi->grf_clk = devm_clk_get(dev, "grf");
+   if (IS_ERR(dsi->grf_clk)) {
+   ret = PTR_ERR(dsi->grf_clk);
+   dev_err(dev, "Unable to get grf_clk: %d\n", ret);
+   return ret;
+   }
}
 
ret = clk_prepare_enable(dsi->pllref_clk);
-- 
2.6.3



[PATCH v2 4/4] drm/rockchip/dsi: correct the grf_switch_reg name

2017-03-15 Thread Chris Zhong
For the RK3399, the grf_switch_reg name should be RK3399_GRF_SOC_CON20,
not RK3399_GRF_SOC_CON19.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index a4c74c7..20ad54d 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -34,7 +34,7 @@
 #define RK3288_DSI0_SEL_VOP_LITBIT(6)
 #define RK3288_DSI1_SEL_VOP_LITBIT(9)
 
-#define RK3399_GRF_SOC_CON19   0x6250
+#define RK3399_GRF_SOC_CON20   0x6250
 #define RK3399_DSI0_SEL_VOP_LITBIT(0)
 #define RK3399_DSI1_SEL_VOP_LITBIT(4)
 
@@ -1147,7 +1147,7 @@ static struct dw_mipi_dsi_plat_data 
rk3288_mipi_dsi_drv_data = {
 static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = {
.dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT,
.dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT,
-   .grf_switch_reg = RK3399_GRF_SOC_CON19,
+   .grf_switch_reg = RK3399_GRF_SOC_CON20,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
.max_data_lanes = 4,
-- 
2.6.3



[PATCH v2 4/4] drm/rockchip/dsi: correct the grf_switch_reg name

2017-03-15 Thread Chris Zhong
For the RK3399, the grf_switch_reg name should be RK3399_GRF_SOC_CON20,
not RK3399_GRF_SOC_CON19.

Signed-off-by: Chris Zhong 
---

Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index a4c74c7..20ad54d 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -34,7 +34,7 @@
 #define RK3288_DSI0_SEL_VOP_LITBIT(6)
 #define RK3288_DSI1_SEL_VOP_LITBIT(9)
 
-#define RK3399_GRF_SOC_CON19   0x6250
+#define RK3399_GRF_SOC_CON20   0x6250
 #define RK3399_DSI0_SEL_VOP_LITBIT(0)
 #define RK3399_DSI1_SEL_VOP_LITBIT(4)
 
@@ -1147,7 +1147,7 @@ static struct dw_mipi_dsi_plat_data 
rk3288_mipi_dsi_drv_data = {
 static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = {
.dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT,
.dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT,
-   .grf_switch_reg = RK3399_GRF_SOC_CON19,
+   .grf_switch_reg = RK3399_GRF_SOC_CON20,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
.max_data_lanes = 4,
-- 
2.6.3



[PATCH v2 0/4] RK3399 dw-mipi-dsi patches

2017-03-15 Thread Chris Zhong
Hi all

This series set the phy_cfg_clk to be a required clock for RK3399, and
add a grf clock control in dw-mipi-dsi driver. And then correct a
register name.


Changes in v2:
- check the grf_clk only for RK3399

Chris Zhong (4):
  drm/rockchip/dsi: check phy_cfg_clk only for RK3399
  dt-bindings: add the grf clock for dw-mipi-dsi
  drm/rockchip/dsi: enable the grf clk before writing grf registers
  drm/rockchip/dsi: correct the grf_switch_reg name

 .../display/rockchip/dw_mipi_dsi_rockchip.txt  |  2 +-
 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 35 +-
 2 files changed, 28 insertions(+), 9 deletions(-)

-- 
2.6.3



[PATCH v2 1/4] drm/rockchip/dsi: check phy_cfg_clk only for RK3399

2017-03-15 Thread Chris Zhong
For RK3399, the phy_cfg_clk is a required clock, if phy_cfg_clk is
disabled, MIPI phy can not work. Let's return a error if there is no
phy_cfg_clk in dts property, when the pdata match RK3399.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index f84f9ae..11c4166 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -1227,15 +1227,13 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
clk_disable_unprepare(dsi->pclk);
}
 
-   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
-   if (IS_ERR(dsi->phy_cfg_clk)) {
-   ret = PTR_ERR(dsi->phy_cfg_clk);
-   if (ret != -ENOENT) {
+   if (pdata == _mipi_dsi_drv_data) {
+   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
+   if (IS_ERR(dsi->phy_cfg_clk)) {
+   ret = PTR_ERR(dsi->phy_cfg_clk);
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
-   dsi->phy_cfg_clk = NULL;
-   dev_dbg(dev, "have not phy_cfg_clk\n");
}
 
ret = clk_prepare_enable(dsi->pllref_clk);
-- 
2.6.3



[PATCH v2 2/4] dt-bindings: add the grf clock for dw-mipi-dsi

2017-03-15 Thread Chris Zhong
For RK3399, the grf clock should be controlled by dw-mipi-dsi driver,
add the description for this clock.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v2: None

 .../devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
index 188f6f7..7e17a60 100644
--- 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
+++ 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
@@ -10,7 +10,7 @@ Required properties:
 - interrupts: Represent the controller's interrupt to the CPU(s).
 - clocks, clock-names: Phandles to the controller's pll reference
   clock(ref) and APB clock(pclk). For RK3399, a phy config clock
-  (phy_cfg) is additional required. As described in [1].
+  (phy_cfg) and a grf clock(grf) are additional required. As described in [1].
 - rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
 - ports: contain a port node with endpoint definitions as defined in [2].
   For vopb,set the reg = <0> and set the reg = <1> for vopl.
-- 
2.6.3



[PATCH v2 0/4] RK3399 dw-mipi-dsi patches

2017-03-15 Thread Chris Zhong
Hi all

This series set the phy_cfg_clk to be a required clock for RK3399, and
add a grf clock control in dw-mipi-dsi driver. And then correct a
register name.


Changes in v2:
- check the grf_clk only for RK3399

Chris Zhong (4):
  drm/rockchip/dsi: check phy_cfg_clk only for RK3399
  dt-bindings: add the grf clock for dw-mipi-dsi
  drm/rockchip/dsi: enable the grf clk before writing grf registers
  drm/rockchip/dsi: correct the grf_switch_reg name

 .../display/rockchip/dw_mipi_dsi_rockchip.txt  |  2 +-
 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 35 +-
 2 files changed, 28 insertions(+), 9 deletions(-)

-- 
2.6.3



[PATCH v2 1/4] drm/rockchip/dsi: check phy_cfg_clk only for RK3399

2017-03-15 Thread Chris Zhong
For RK3399, the phy_cfg_clk is a required clock, if phy_cfg_clk is
disabled, MIPI phy can not work. Let's return a error if there is no
phy_cfg_clk in dts property, when the pdata match RK3399.

Signed-off-by: Chris Zhong 
---

Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index f84f9ae..11c4166 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -1227,15 +1227,13 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
clk_disable_unprepare(dsi->pclk);
}
 
-   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
-   if (IS_ERR(dsi->phy_cfg_clk)) {
-   ret = PTR_ERR(dsi->phy_cfg_clk);
-   if (ret != -ENOENT) {
+   if (pdata == _mipi_dsi_drv_data) {
+   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
+   if (IS_ERR(dsi->phy_cfg_clk)) {
+   ret = PTR_ERR(dsi->phy_cfg_clk);
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
-   dsi->phy_cfg_clk = NULL;
-   dev_dbg(dev, "have not phy_cfg_clk\n");
}
 
ret = clk_prepare_enable(dsi->pllref_clk);
-- 
2.6.3



[PATCH v2 2/4] dt-bindings: add the grf clock for dw-mipi-dsi

2017-03-15 Thread Chris Zhong
For RK3399, the grf clock should be controlled by dw-mipi-dsi driver,
add the description for this clock.

Signed-off-by: Chris Zhong 
---

Changes in v2: None

 .../devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
index 188f6f7..7e17a60 100644
--- 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
+++ 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
@@ -10,7 +10,7 @@ Required properties:
 - interrupts: Represent the controller's interrupt to the CPU(s).
 - clocks, clock-names: Phandles to the controller's pll reference
   clock(ref) and APB clock(pclk). For RK3399, a phy config clock
-  (phy_cfg) is additional required. As described in [1].
+  (phy_cfg) and a grf clock(grf) are additional required. As described in [1].
 - rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
 - ports: contain a port node with endpoint definitions as defined in [2].
   For vopb,set the reg = <0> and set the reg = <1> for vopl.
-- 
2.6.3



Re: [PATCH 1/3] dt-bindings: add the grf clock for dw-mipi-dsi

2017-03-15 Thread Chris Zhong

Hi Heiko

On 03/15/2017 05:03 PM, Heiko Stübner wrote:

Am Mittwoch, 15. März 2017, 16:42:30 CET schrieb Chris Zhong:

For RK3399, the grf clock should be controlled by dw-mipi-dsi driver,
add the description for this clock.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

  .../devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt   | 2
+- 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.t
xt
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.t
xt index 188f6f7..7e17a60 100644
---
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.t
xt +++
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.t
xt @@ -10,7 +10,7 @@ Required properties:
  - interrupts: Represent the controller's interrupt to the CPU(s).
  - clocks, clock-names: Phandles to the controller's pll reference
clock(ref) and APB clock(pclk). For RK3399, a phy config clock
-  (phy_cfg) is additional required. As described in [1].
+  (phy_cfg) and a grf clock(grf) are additional required. As described in
[1].

your "grf" clock is optional, as it is not present on all socs (like the
rk3288) so should probably move to a separate section and not be in the
required properties
For RK3399, the grf clock is required, according to the advice provided 
by rob[0],

put it into "required properties " is better.
[0] https://patchwork.kernel.org/patch/9220187/


Heiko





--
Chris Zhong




Re: [PATCH 1/3] dt-bindings: add the grf clock for dw-mipi-dsi

2017-03-15 Thread Chris Zhong

Hi Heiko

On 03/15/2017 05:03 PM, Heiko Stübner wrote:

Am Mittwoch, 15. März 2017, 16:42:30 CET schrieb Chris Zhong:

For RK3399, the grf clock should be controlled by dw-mipi-dsi driver,
add the description for this clock.

Signed-off-by: Chris Zhong 
---

  .../devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt   | 2
+- 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.t
xt
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.t
xt index 188f6f7..7e17a60 100644
---
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.t
xt +++
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.t
xt @@ -10,7 +10,7 @@ Required properties:
  - interrupts: Represent the controller's interrupt to the CPU(s).
  - clocks, clock-names: Phandles to the controller's pll reference
clock(ref) and APB clock(pclk). For RK3399, a phy config clock
-  (phy_cfg) is additional required. As described in [1].
+  (phy_cfg) and a grf clock(grf) are additional required. As described in
[1].

your "grf" clock is optional, as it is not present on all socs (like the
rk3288) so should probably move to a separate section and not be in the
required properties
For RK3399, the grf clock is required, according to the advice provided 
by rob[0],

put it into "required properties " is better.
[0] https://patchwork.kernel.org/patch/9220187/


Heiko





--
Chris Zhong




[PATCH 3/3] drm/rockchip/dsi: correct the grf_switch_reg name

2017-03-15 Thread Chris Zhong
For the RK3399, the grf_switch_reg name should be RK3399_GRF_SOC_CON20,
not RK3399_GRF_SOC_CON19.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index d8f24f2..ddd5dba 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -34,7 +34,7 @@
 #define RK3288_DSI0_SEL_VOP_LITBIT(6)
 #define RK3288_DSI1_SEL_VOP_LITBIT(9)
 
-#define RK3399_GRF_SOC_CON19   0x6250
+#define RK3399_GRF_SOC_CON20   0x6250
 #define RK3399_DSI0_SEL_VOP_LITBIT(0)
 #define RK3399_DSI1_SEL_VOP_LITBIT(4)
 
@@ -1146,7 +1146,7 @@ static struct dw_mipi_dsi_plat_data 
rk3288_mipi_dsi_drv_data = {
 static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = {
.dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT,
.dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT,
-   .grf_switch_reg = RK3399_GRF_SOC_CON19,
+   .grf_switch_reg = RK3399_GRF_SOC_CON20,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
.max_data_lanes = 4,
-- 
2.6.3



[PATCH 2/3] drm/rockchip/dsi: enable the grf clk before writing grf registers

2017-03-15 Thread Chris Zhong
For RK3399, the grf clk should be enabled before writing grf registers,
otherwise the register value can not be changed.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index f84f9ae..d8f24f2 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -291,6 +291,7 @@ struct dw_mipi_dsi {
struct regmap *grf_regmap;
void __iomem *base;
 
+   struct clk *grf_clk;
struct clk *pllref_clk;
struct clk *pclk;
struct clk *phy_cfg_clk;
@@ -979,6 +980,16 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
dw_mipi_dsi_dphy_interface_config(dsi);
dw_mipi_dsi_clear_err(dsi);
 
+   /*
+* For the RK3399, the clk of grf must be enabled before writing grf
+* register.
+*/
+   ret = clk_prepare_enable(dsi->grf_clk);
+   if (ret) {
+   dev_err(dsi->dev, "Failed to enable grf_clk\n");
+   return;
+   }
+
if (pdata->grf_dsi0_mode_reg)
regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
 pdata->grf_dsi0_mode);
@@ -1003,6 +1014,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val);
dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
dsi->dpms_mode = DRM_MODE_DPMS_ON;
+
+   clk_disable_unprepare(dsi->grf_clk);
 }
 
 static int
@@ -1238,6 +1251,17 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
dev_dbg(dev, "have not phy_cfg_clk\n");
}
 
+   dsi->grf_clk = devm_clk_get(dev, "grf");
+   if (IS_ERR(dsi->grf_clk)) {
+   ret = PTR_ERR(dsi->grf_clk);
+   if (ret != -ENOENT) {
+   dev_err(dev, "Unable to get grf_clk: %d\n", ret);
+   return ret;
+   }
+   dsi->grf_clk = NULL;
+   dev_dbg(dev, "have not grf_clk\n");
+   }
+
ret = clk_prepare_enable(dsi->pllref_clk);
if (ret) {
dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);
-- 
2.6.3



[PATCH 1/3] dt-bindings: add the grf clock for dw-mipi-dsi

2017-03-15 Thread Chris Zhong
For RK3399, the grf clock should be controlled by dw-mipi-dsi driver,
add the description for this clock.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

 .../devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
index 188f6f7..7e17a60 100644
--- 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
+++ 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
@@ -10,7 +10,7 @@ Required properties:
 - interrupts: Represent the controller's interrupt to the CPU(s).
 - clocks, clock-names: Phandles to the controller's pll reference
   clock(ref) and APB clock(pclk). For RK3399, a phy config clock
-  (phy_cfg) is additional required. As described in [1].
+  (phy_cfg) and a grf clock(grf) are additional required. As described in [1].
 - rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
 - ports: contain a port node with endpoint definitions as defined in [2].
   For vopb,set the reg = <0> and set the reg = <1> for vopl.
-- 
2.6.3



[PATCH 3/3] drm/rockchip/dsi: correct the grf_switch_reg name

2017-03-15 Thread Chris Zhong
For the RK3399, the grf_switch_reg name should be RK3399_GRF_SOC_CON20,
not RK3399_GRF_SOC_CON19.

Signed-off-by: Chris Zhong 
---

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index d8f24f2..ddd5dba 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -34,7 +34,7 @@
 #define RK3288_DSI0_SEL_VOP_LITBIT(6)
 #define RK3288_DSI1_SEL_VOP_LITBIT(9)
 
-#define RK3399_GRF_SOC_CON19   0x6250
+#define RK3399_GRF_SOC_CON20   0x6250
 #define RK3399_DSI0_SEL_VOP_LITBIT(0)
 #define RK3399_DSI1_SEL_VOP_LITBIT(4)
 
@@ -1146,7 +1146,7 @@ static struct dw_mipi_dsi_plat_data 
rk3288_mipi_dsi_drv_data = {
 static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = {
.dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT,
.dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT,
-   .grf_switch_reg = RK3399_GRF_SOC_CON19,
+   .grf_switch_reg = RK3399_GRF_SOC_CON20,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
.max_data_lanes = 4,
-- 
2.6.3



[PATCH 2/3] drm/rockchip/dsi: enable the grf clk before writing grf registers

2017-03-15 Thread Chris Zhong
For RK3399, the grf clk should be enabled before writing grf registers,
otherwise the register value can not be changed.

Signed-off-by: Chris Zhong 
---

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index f84f9ae..d8f24f2 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -291,6 +291,7 @@ struct dw_mipi_dsi {
struct regmap *grf_regmap;
void __iomem *base;
 
+   struct clk *grf_clk;
struct clk *pllref_clk;
struct clk *pclk;
struct clk *phy_cfg_clk;
@@ -979,6 +980,16 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
dw_mipi_dsi_dphy_interface_config(dsi);
dw_mipi_dsi_clear_err(dsi);
 
+   /*
+* For the RK3399, the clk of grf must be enabled before writing grf
+* register.
+*/
+   ret = clk_prepare_enable(dsi->grf_clk);
+   if (ret) {
+   dev_err(dsi->dev, "Failed to enable grf_clk\n");
+   return;
+   }
+
if (pdata->grf_dsi0_mode_reg)
regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
 pdata->grf_dsi0_mode);
@@ -1003,6 +1014,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val);
dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
dsi->dpms_mode = DRM_MODE_DPMS_ON;
+
+   clk_disable_unprepare(dsi->grf_clk);
 }
 
 static int
@@ -1238,6 +1251,17 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
dev_dbg(dev, "have not phy_cfg_clk\n");
}
 
+   dsi->grf_clk = devm_clk_get(dev, "grf");
+   if (IS_ERR(dsi->grf_clk)) {
+   ret = PTR_ERR(dsi->grf_clk);
+   if (ret != -ENOENT) {
+   dev_err(dev, "Unable to get grf_clk: %d\n", ret);
+   return ret;
+   }
+   dsi->grf_clk = NULL;
+   dev_dbg(dev, "have not grf_clk\n");
+   }
+
ret = clk_prepare_enable(dsi->pllref_clk);
if (ret) {
dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);
-- 
2.6.3



[PATCH 1/3] dt-bindings: add the grf clock for dw-mipi-dsi

2017-03-15 Thread Chris Zhong
For RK3399, the grf clock should be controlled by dw-mipi-dsi driver,
add the description for this clock.

Signed-off-by: Chris Zhong 
---

 .../devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
index 188f6f7..7e17a60 100644
--- 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
+++ 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
@@ -10,7 +10,7 @@ Required properties:
 - interrupts: Represent the controller's interrupt to the CPU(s).
 - clocks, clock-names: Phandles to the controller's pll reference
   clock(ref) and APB clock(pclk). For RK3399, a phy config clock
-  (phy_cfg) is additional required. As described in [1].
+  (phy_cfg) and a grf clock(grf) are additional required. As described in [1].
 - rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
 - ports: contain a port node with endpoint definitions as defined in [2].
   For vopb,set the reg = <0> and set the reg = <1> for vopl.
-- 
2.6.3



[PATCH v2 2/2] drm/panel: add innolux,p079zca panel driver

2017-03-15 Thread Chris Zhong
Support Innolux P079ZCA 7.85" 768x1024 TFT LCD panel, it is a MIPI DSI
panel.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v2:
- add some error check
- always use Low power mode to send commend
- add comments for all the sleep
- use DRM_DEV_ERROR instead of dev_err

 drivers/gpu/drm/panel/Kconfig |  11 +
 drivers/gpu/drm/panel/Makefile|   1 +
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 344 ++
 3 files changed, 356 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-innolux-p079zca.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 62aba97..99dd010 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -18,6 +18,17 @@ config DRM_PANEL_SIMPLE
  that it can be automatically turned off when the panel goes into a
  low power state.
 
+config DRM_PANEL_INNOLUX_P079ZCA
+   tristate "Innolux P079ZCA panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   depends on BACKLIGHT_CLASS_DEVICE
+   help
+ Say Y here if you want to enable support for Innolux P079ZCA
+ TFT-LCD modules. The panel has a 1024x768 resolution and uses
+ 24 bit RGB per pixel. It provides a MIPI DSI interface to
+ the host and has a built-in LED backlight.
+
 config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index a5c7ec0..bda2aa4 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
+obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
 obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
new file mode 100644
index 000..b8c34e0
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct innolux_panel {
+   struct drm_panel base;
+   struct mipi_dsi_device *link;
+
+   struct backlight_device *backlight;
+   struct regulator *supply;
+   struct gpio_desc *enable_gpio;
+
+   bool prepared;
+   bool enabled;
+};
+
+static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel)
+{
+   return container_of(panel, struct innolux_panel, base);
+}
+
+static int innolux_panel_disable(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->enabled)
+   return 0;
+
+   if (innolux->backlight) {
+   innolux->backlight->props.power = FB_BLANK_POWERDOWN;
+   backlight_update_status(innolux->backlight);
+   }
+
+   err = mipi_dsi_dcs_set_display_off(innolux->link);
+   if (err < 0)
+   DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n",
+ err);
+
+   innolux->enabled = false;
+
+   return 0;
+}
+
+static int innolux_panel_unprepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->prepared)
+   return 0;
+
+   err = mipi_dsi_dcs_enter_sleep_mode(innolux->link);
+   if (err < 0) {
+   DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n",
+ err);
+   return err;
+   }
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+
+   /* T8: 80ms - 1000ms */
+   msleep(80);
+
+   err = regulator_disable(innolux->supply);
+   if (err < 0)
+   return err;
+
+   innolux->prepared = false;
+
+   return 0;
+}
+
+static int innolux_panel_prepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err, ret;
+
+   if (innolux->prepared)
+   return 0;
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+
+   err = regulator_enable(innolux->supply);
+   if (err < 0)
+   return err;
+
+   /* T2: 15ms - 1000ms */
+   uslee

[PATCH v2 1/2] dt-bindings: Add INNOLUX P079ZCA panel bindings

2017-03-15 Thread Chris Zhong
The Innolux P079ZCA is a 7.85" panel with a 768X1024 resolution and
connected to DSI using four lanes.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

Changes in v2: None

 .../bindings/display/panel/innolux,p079zca.txt | 23 ++
 1 file changed, 23 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt

diff --git 
a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt 
b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
new file mode 100644
index 000..5c70a83
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
@@ -0,0 +1,23 @@
+Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,p079zca"
+- reg: DSI virtual channel of the peripheral
+- power-supply: phandle of the regulator that provides the supply voltage
+- enable-gpios: panel enable gpio
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+   _dsi {
+   panel {
+   compatible = "innolux,p079zca";
+   reg = <0>;
+   power-supply = <...>;
+   backlight = <>;
+   enable-gpios = < 13 GPIO_ACTIVE_HIGH>;
+   status = "okay";
+   };
+   };
-- 
2.6.3



[PATCH v2 2/2] drm/panel: add innolux,p079zca panel driver

2017-03-15 Thread Chris Zhong
Support Innolux P079ZCA 7.85" 768x1024 TFT LCD panel, it is a MIPI DSI
panel.

Signed-off-by: Chris Zhong 
---

Changes in v2:
- add some error check
- always use Low power mode to send commend
- add comments for all the sleep
- use DRM_DEV_ERROR instead of dev_err

 drivers/gpu/drm/panel/Kconfig |  11 +
 drivers/gpu/drm/panel/Makefile|   1 +
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 344 ++
 3 files changed, 356 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-innolux-p079zca.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 62aba97..99dd010 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -18,6 +18,17 @@ config DRM_PANEL_SIMPLE
  that it can be automatically turned off when the panel goes into a
  low power state.
 
+config DRM_PANEL_INNOLUX_P079ZCA
+   tristate "Innolux P079ZCA panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   depends on BACKLIGHT_CLASS_DEVICE
+   help
+ Say Y here if you want to enable support for Innolux P079ZCA
+ TFT-LCD modules. The panel has a 1024x768 resolution and uses
+ 24 bit RGB per pixel. It provides a MIPI DSI interface to
+ the host and has a built-in LED backlight.
+
 config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index a5c7ec0..bda2aa4 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
+obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
 obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
new file mode 100644
index 000..b8c34e0
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct innolux_panel {
+   struct drm_panel base;
+   struct mipi_dsi_device *link;
+
+   struct backlight_device *backlight;
+   struct regulator *supply;
+   struct gpio_desc *enable_gpio;
+
+   bool prepared;
+   bool enabled;
+};
+
+static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel)
+{
+   return container_of(panel, struct innolux_panel, base);
+}
+
+static int innolux_panel_disable(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->enabled)
+   return 0;
+
+   if (innolux->backlight) {
+   innolux->backlight->props.power = FB_BLANK_POWERDOWN;
+   backlight_update_status(innolux->backlight);
+   }
+
+   err = mipi_dsi_dcs_set_display_off(innolux->link);
+   if (err < 0)
+   DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n",
+ err);
+
+   innolux->enabled = false;
+
+   return 0;
+}
+
+static int innolux_panel_unprepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->prepared)
+   return 0;
+
+   err = mipi_dsi_dcs_enter_sleep_mode(innolux->link);
+   if (err < 0) {
+   DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n",
+ err);
+   return err;
+   }
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+
+   /* T8: 80ms - 1000ms */
+   msleep(80);
+
+   err = regulator_disable(innolux->supply);
+   if (err < 0)
+   return err;
+
+   innolux->prepared = false;
+
+   return 0;
+}
+
+static int innolux_panel_prepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err, ret;
+
+   if (innolux->prepared)
+   return 0;
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+
+   err = regulator_enable(innolux->supply);
+   if (err < 0)
+   return err;
+
+   /* T2: 15ms - 1000ms */
+   usleep_range(15000, 16000);
+
+   gpiod_set_

[PATCH v2 1/2] dt-bindings: Add INNOLUX P079ZCA panel bindings

2017-03-15 Thread Chris Zhong
The Innolux P079ZCA is a 7.85" panel with a 768X1024 resolution and
connected to DSI using four lanes.

Signed-off-by: Chris Zhong 
---

Changes in v2: None

 .../bindings/display/panel/innolux,p079zca.txt | 23 ++
 1 file changed, 23 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt

diff --git 
a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt 
b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
new file mode 100644
index 000..5c70a83
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
@@ -0,0 +1,23 @@
+Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,p079zca"
+- reg: DSI virtual channel of the peripheral
+- power-supply: phandle of the regulator that provides the supply voltage
+- enable-gpios: panel enable gpio
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+   _dsi {
+   panel {
+   compatible = "innolux,p079zca";
+   reg = <0>;
+   power-supply = <...>;
+   backlight = <>;
+   enable-gpios = < 13 GPIO_ACTIVE_HIGH>;
+   status = "okay";
+   };
+   };
-- 
2.6.3



Re: [PATCH 3/4] phy: rockchip-typec: support DP phy switch

2017-03-08 Thread Chris Zhong

Hi Heiko and Brain

On 03/09/2017 09:02 AM, Heiko Stübner wrote:

Am Mittwoch, 8. März 2017, 16:39:23 CET schrieb Brian Norris:

On Fri, Feb 10, 2017 at 03:44:13PM +0800, Chris Zhong wrote:

There are 2 Type-c PHYs in RK3399, but only one DP controller. Hence
only one PHY can connect to DP controller at one time, the other should
be disconnected. The GRF_SOC_CON26 register has a switch bit to do it,
set this bit means enable PHY 1, clear this bit means enable PHY 0.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

  drivers/phy/phy-rockchip-typec.c | 9 +
  1 file changed, 9 insertions(+)

diff --git a/drivers/phy/phy-rockchip-typec.c
b/drivers/phy/phy-rockchip-typec.c index 7cfb0f8..1604aaa 100644
--- a/drivers/phy/phy-rockchip-typec.c
+++ b/drivers/phy/phy-rockchip-typec.c
@@ -267,6 +267,7 @@ struct rockchip_usb3phy_port_cfg {

struct usb3phy_reg usb3tousb2_en;
struct usb3phy_reg external_psm;
struct usb3phy_reg pipe_status;

+   struct usb3phy_reg uphy_dp_sel;

  };
  
  struct rockchip_typec_phy {


@@ -736,6 +737,7 @@ static const struct phy_ops rockchip_usb3_phy_ops = {

  static int rockchip_dp_phy_power_on(struct phy *phy)
  {
  
  	struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);


+   struct rockchip_usb3phy_port_cfg *cfg = >port_cfgs;

int new_mode, ret = 0;
u32 val;

@@ -766,6 +768,8 @@ static int rockchip_dp_phy_power_on(struct phy *phy)

tcphy_phy_init(tcphy, new_mode);

}

+   property_enable(tcphy, >uphy_dp_sel, 1);
+

ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,

Idea for future work: this should just be readl_poll_timeout() here, and
throughout the driver.
Yes, the readl_poll_timeout is better, if next version series is needed, 
I am going to

add it in a separate patch behind this patch.

 val, val & DP_MODE_A2, 1000,
 PHY_MODE_SET_TIMEOUT);

@@ -869,6 +873,11 @@ static int tcphy_parse_dt(struct rockchip_typec_phy
*tcphy,>
if (ret)

return ret;

+   ret = tcphy_get_param(dev, >uphy_dp_sel,
+ "rockchip,uphy-dp-sel");
+   if (ret)
+   return ret;

What about existing device trees? You're essentially adding this
new property and requiring it at the same time.

Or are we considering no RK3399 DP stable at the moment? I guess we
haven't actually merged any device trees that support this yet, no?

An interesting situation we're in here. On the one hand, you're right this
breaks "backwards compatiblity".

But on the other hand, the type-c phy is currently very much unused. The only
current board rk3399-evb.dts does not enable them (so they're disabled
everywhere) and we have neither dwc3 nor dp nodes in any rk3399 devicetrees so
far. Also Rob was ok with the binding change :-) .

So from my pov, I'd say it _should_ be ok, as nothing is using the phys at all
yet and thus there is nothing that could get broken.


Heiko
Thanks Heiko. On the other hand, these is no any display node at rk3399 
dtsi,

so I can not add the DP node, do you or Mark.Yao have plan to complete it?




Brian


+

tcphy->grf_regs = syscon_regmap_lookup_by_phandle(dev->of_node,

  "rockchip,grf");
    
if (IS_ERR(tcphy->grf_regs)) {







--
Chris Zhong




Re: [PATCH 3/4] phy: rockchip-typec: support DP phy switch

2017-03-08 Thread Chris Zhong

Hi Heiko and Brain

On 03/09/2017 09:02 AM, Heiko Stübner wrote:

Am Mittwoch, 8. März 2017, 16:39:23 CET schrieb Brian Norris:

On Fri, Feb 10, 2017 at 03:44:13PM +0800, Chris Zhong wrote:

There are 2 Type-c PHYs in RK3399, but only one DP controller. Hence
only one PHY can connect to DP controller at one time, the other should
be disconnected. The GRF_SOC_CON26 register has a switch bit to do it,
set this bit means enable PHY 1, clear this bit means enable PHY 0.

Signed-off-by: Chris Zhong 
---

  drivers/phy/phy-rockchip-typec.c | 9 +
  1 file changed, 9 insertions(+)

diff --git a/drivers/phy/phy-rockchip-typec.c
b/drivers/phy/phy-rockchip-typec.c index 7cfb0f8..1604aaa 100644
--- a/drivers/phy/phy-rockchip-typec.c
+++ b/drivers/phy/phy-rockchip-typec.c
@@ -267,6 +267,7 @@ struct rockchip_usb3phy_port_cfg {

struct usb3phy_reg usb3tousb2_en;
struct usb3phy_reg external_psm;
struct usb3phy_reg pipe_status;

+   struct usb3phy_reg uphy_dp_sel;

  };
  
  struct rockchip_typec_phy {


@@ -736,6 +737,7 @@ static const struct phy_ops rockchip_usb3_phy_ops = {

  static int rockchip_dp_phy_power_on(struct phy *phy)
  {
  
  	struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);


+   struct rockchip_usb3phy_port_cfg *cfg = >port_cfgs;

int new_mode, ret = 0;
u32 val;

@@ -766,6 +768,8 @@ static int rockchip_dp_phy_power_on(struct phy *phy)

tcphy_phy_init(tcphy, new_mode);

}

+   property_enable(tcphy, >uphy_dp_sel, 1);
+

ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,

Idea for future work: this should just be readl_poll_timeout() here, and
throughout the driver.
Yes, the readl_poll_timeout is better, if next version series is needed, 
I am going to

add it in a separate patch behind this patch.

 val, val & DP_MODE_A2, 1000,
 PHY_MODE_SET_TIMEOUT);

@@ -869,6 +873,11 @@ static int tcphy_parse_dt(struct rockchip_typec_phy
*tcphy,>
if (ret)

return ret;

+   ret = tcphy_get_param(dev, >uphy_dp_sel,
+ "rockchip,uphy-dp-sel");
+   if (ret)
+   return ret;

What about existing device trees? You're essentially adding this
new property and requiring it at the same time.

Or are we considering no RK3399 DP stable at the moment? I guess we
haven't actually merged any device trees that support this yet, no?

An interesting situation we're in here. On the one hand, you're right this
breaks "backwards compatiblity".

But on the other hand, the type-c phy is currently very much unused. The only
current board rk3399-evb.dts does not enable them (so they're disabled
everywhere) and we have neither dwc3 nor dp nodes in any rk3399 devicetrees so
far. Also Rob was ok with the binding change :-) .

So from my pov, I'd say it _should_ be ok, as nothing is using the phys at all
yet and thus there is nothing that could get broken.


Heiko
Thanks Heiko. On the other hand, these is no any display node at rk3399 
dtsi,

so I can not add the DP node, do you or Mark.Yao have plan to complete it?




Brian


+

tcphy->grf_regs = syscon_regmap_lookup_by_phandle(dev->of_node,

  "rockchip,grf");
    
    if (IS_ERR(tcphy->grf_regs)) {







--
Chris Zhong




[PATCH 2/3] drm/rockchip: cdn-dp: Correct PHY register address

2017-03-07 Thread Chris Zhong
Correct some DP register address for PHY Configuration according to
latest datasheet.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

 drivers/gpu/drm/rockchip/cdn-dp-reg.h | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index 3507be3..c4bbb4a83 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -121,12 +121,11 @@
 
 /* dptx phy addr */
 #define DP_TX_PHY_CONFIG_REG   0x2000
-#define DP_TX_PHY_STATUS_REG   0x2004
-#define DP_TX_PHY_SW_RESET 0x2008
-#define DP_TX_PHY_SCRAMBLER_SEED   0x200c
-#define DP_TX_PHY_TRAINING_01_04   0x2010
-#define DP_TX_PHY_TRAINING_05_08   0x2014
-#define DP_TX_PHY_TRAINING_09_10   0x2018
+#define DP_TX_PHY_SW_RESET 0x2004
+#define DP_TX_PHY_SCRAMBLER_SEED   0x2008
+#define DP_TX_PHY_TRAINING_01_04   0x200c
+#define DP_TX_PHY_TRAINING_05_08   0x2010
+#define DP_TX_PHY_TRAINING_09_10   0x2014
 #define TEST_COR   0x23fc
 
 /* dptx hpd addr */
-- 
2.6.3



[PATCH 2/3] drm/rockchip: cdn-dp: Correct PHY register address

2017-03-07 Thread Chris Zhong
Correct some DP register address for PHY Configuration according to
latest datasheet.

Signed-off-by: Chris Zhong 
---

 drivers/gpu/drm/rockchip/cdn-dp-reg.h | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index 3507be3..c4bbb4a83 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -121,12 +121,11 @@
 
 /* dptx phy addr */
 #define DP_TX_PHY_CONFIG_REG   0x2000
-#define DP_TX_PHY_STATUS_REG   0x2004
-#define DP_TX_PHY_SW_RESET 0x2008
-#define DP_TX_PHY_SCRAMBLER_SEED   0x200c
-#define DP_TX_PHY_TRAINING_01_04   0x2010
-#define DP_TX_PHY_TRAINING_05_08   0x2014
-#define DP_TX_PHY_TRAINING_09_10   0x2018
+#define DP_TX_PHY_SW_RESET 0x2004
+#define DP_TX_PHY_SCRAMBLER_SEED   0x2008
+#define DP_TX_PHY_TRAINING_01_04   0x200c
+#define DP_TX_PHY_TRAINING_05_08   0x2010
+#define DP_TX_PHY_TRAINING_09_10   0x2014
 #define TEST_COR   0x23fc
 
 /* dptx hpd addr */
-- 
2.6.3



Re: [PATCH 0/3] RK3399 cdd-dp patches

2017-03-07 Thread Chris Zhong

Oh, a slip of the finger :(, the headline should be "RK3399 cdn-dp patches"

On 03/08/2017 10:27 AM, Chris Zhong wrote:

Hi all
This series is to correct some mistakes in clk_get_rate and the register
address. And in order to better develop, adding more prints.


Chris Zhong (3):
   drm/rockchip: cdn-dp: return error code when clk_get_rate failed
   drm/rockchip: cdn-dp: Correct PHY register address
   drm/rockchip: cdn-dp: add more log for video config

  drivers/gpu/drm/rockchip/cdn-dp-core.c |  5 +++--
  drivers/gpu/drm/rockchip/cdn-dp-reg.c  |  6 +-
  drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 13 ++---
  3 files changed, 14 insertions(+), 10 deletions(-)



--
Chris Zhong




Re: [PATCH 0/3] RK3399 cdd-dp patches

2017-03-07 Thread Chris Zhong

Oh, a slip of the finger :(, the headline should be "RK3399 cdn-dp patches"

On 03/08/2017 10:27 AM, Chris Zhong wrote:

Hi all
This series is to correct some mistakes in clk_get_rate and the register
address. And in order to better develop, adding more prints.


Chris Zhong (3):
   drm/rockchip: cdn-dp: return error code when clk_get_rate failed
   drm/rockchip: cdn-dp: Correct PHY register address
   drm/rockchip: cdn-dp: add more log for video config

  drivers/gpu/drm/rockchip/cdn-dp-core.c |  5 +++--
  drivers/gpu/drm/rockchip/cdn-dp-reg.c  |  6 +-
  drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 13 ++---
  3 files changed, 14 insertions(+), 10 deletions(-)



--
Chris Zhong




[PATCH 3/3] drm/rockchip: cdn-dp: add more log for video config

2017-03-07 Thread Chris Zhong
In order to analyze some video config failed, add some useful
printouts.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

 drivers/gpu/drm/rockchip/cdn-dp-reg.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index 963d8ab..b14d211 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -671,6 +671,10 @@ int cdn_dp_config_video(struct cdn_dp_device *dp)
rem = do_div(symbol, 1000);
if (tu_size_reg > 64) {
ret = -EINVAL;
+   DRM_DEV_ERROR(dp->dev,
+ "tu error, clk:%d, lanes:%d, rate:%d\n",
+ mode->clock, dp->link.num_lanes,
+ link_rate);
goto err_config_video;
}
} while ((symbol <= 1) || (tu_size_reg - symbol < 4) ||
-- 
2.6.3



[PATCH 0/3] RK3399 cdd-dp patches

2017-03-07 Thread Chris Zhong
Hi all
This series is to correct some mistakes in clk_get_rate and the register
address. And in order to better develop, adding more prints.


Chris Zhong (3):
  drm/rockchip: cdn-dp: return error code when clk_get_rate failed
  drm/rockchip: cdn-dp: Correct PHY register address
  drm/rockchip: cdn-dp: add more log for video config

 drivers/gpu/drm/rockchip/cdn-dp-core.c |  5 +++--
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  |  6 +-
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 13 ++---
 3 files changed, 14 insertions(+), 10 deletions(-)

-- 
2.6.3



[PATCH 3/3] drm/rockchip: cdn-dp: add more log for video config

2017-03-07 Thread Chris Zhong
In order to analyze some video config failed, add some useful
printouts.

Signed-off-by: Chris Zhong 
---

 drivers/gpu/drm/rockchip/cdn-dp-reg.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index 963d8ab..b14d211 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -671,6 +671,10 @@ int cdn_dp_config_video(struct cdn_dp_device *dp)
rem = do_div(symbol, 1000);
if (tu_size_reg > 64) {
ret = -EINVAL;
+   DRM_DEV_ERROR(dp->dev,
+ "tu error, clk:%d, lanes:%d, rate:%d\n",
+ mode->clock, dp->link.num_lanes,
+ link_rate);
goto err_config_video;
}
} while ((symbol <= 1) || (tu_size_reg - symbol < 4) ||
-- 
2.6.3



[PATCH 0/3] RK3399 cdd-dp patches

2017-03-07 Thread Chris Zhong
Hi all
This series is to correct some mistakes in clk_get_rate and the register
address. And in order to better develop, adding more prints.


Chris Zhong (3):
  drm/rockchip: cdn-dp: return error code when clk_get_rate failed
  drm/rockchip: cdn-dp: Correct PHY register address
  drm/rockchip: cdn-dp: add more log for video config

 drivers/gpu/drm/rockchip/cdn-dp-core.c |  5 +++--
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  |  6 +-
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 13 ++---
 3 files changed, 14 insertions(+), 10 deletions(-)

-- 
2.6.3



[PATCH 1/3] drm/rockchip: cdn-dp: return error code when clk_get_rate failed

2017-03-07 Thread Chris Zhong
The clk_get_rate return 0 if something goes wrong, so it can never be
less then zero, the ret should be set a error code, otherwise the
cdn_dp_clk_enable will return 0 when it failed at clk_get_rate.
In addition, clk_get_rate() returns an "unsigned long", so use
"unsigned long" instead of "u32" is better.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 5 +++--
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 2 +-
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index fd79a70..9edb8dc 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -94,7 +94,7 @@ static int cdn_dp_grf_write(struct cdn_dp_device *dp,
 static int cdn_dp_clk_enable(struct cdn_dp_device *dp)
 {
int ret;
-   u32 rate;
+   unsigned long rate;
 
ret = clk_prepare_enable(dp->pclk);
if (ret < 0) {
@@ -123,7 +123,8 @@ static int cdn_dp_clk_enable(struct cdn_dp_device *dp)
 
rate = clk_get_rate(dp->core_clk);
if (!rate) {
-   DRM_DEV_ERROR(dp->dev, "get clk rate failed: %d\n", rate);
+   DRM_DEV_ERROR(dp->dev, "get clk rate failed\n");
+   ret = -EINVAL;
goto err_set_rate;
}
 
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index 319dbba..963d8ab 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -29,7 +29,7 @@
 #define LINK_TRAINING_RETRY_MS 20
 #define LINK_TRAINING_TIMEOUT_MS   500
 
-void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, u32 clk)
+void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, unsigned long clk)
 {
writel(clk / 100, dp->regs + SW_CLK_H);
 }
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index b5f2153..3507be3 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -462,7 +462,7 @@ enum vic_bt_type {
 
 void cdn_dp_clock_reset(struct cdn_dp_device *dp);
 
-void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, u32 clk);
+void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, unsigned long clk);
 int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem,
 u32 i_size, const u32 *d_mem, u32 d_size);
 int cdn_dp_set_firmware_active(struct cdn_dp_device *dp, bool enable);
-- 
2.6.3



[PATCH 1/3] drm/rockchip: cdn-dp: return error code when clk_get_rate failed

2017-03-07 Thread Chris Zhong
The clk_get_rate return 0 if something goes wrong, so it can never be
less then zero, the ret should be set a error code, otherwise the
cdn_dp_clk_enable will return 0 when it failed at clk_get_rate.
In addition, clk_get_rate() returns an "unsigned long", so use
"unsigned long" instead of "u32" is better.

Signed-off-by: Chris Zhong 
---

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 5 +++--
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 2 +-
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index fd79a70..9edb8dc 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -94,7 +94,7 @@ static int cdn_dp_grf_write(struct cdn_dp_device *dp,
 static int cdn_dp_clk_enable(struct cdn_dp_device *dp)
 {
int ret;
-   u32 rate;
+   unsigned long rate;
 
ret = clk_prepare_enable(dp->pclk);
if (ret < 0) {
@@ -123,7 +123,8 @@ static int cdn_dp_clk_enable(struct cdn_dp_device *dp)
 
rate = clk_get_rate(dp->core_clk);
if (!rate) {
-   DRM_DEV_ERROR(dp->dev, "get clk rate failed: %d\n", rate);
+   DRM_DEV_ERROR(dp->dev, "get clk rate failed\n");
+   ret = -EINVAL;
goto err_set_rate;
}
 
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index 319dbba..963d8ab 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -29,7 +29,7 @@
 #define LINK_TRAINING_RETRY_MS 20
 #define LINK_TRAINING_TIMEOUT_MS   500
 
-void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, u32 clk)
+void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, unsigned long clk)
 {
writel(clk / 100, dp->regs + SW_CLK_H);
 }
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index b5f2153..3507be3 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -462,7 +462,7 @@ enum vic_bt_type {
 
 void cdn_dp_clock_reset(struct cdn_dp_device *dp);
 
-void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, u32 clk);
+void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, unsigned long clk);
 int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem,
 u32 i_size, const u32 *d_mem, u32 d_size);
 int cdn_dp_set_firmware_active(struct cdn_dp_device *dp, bool enable);
-- 
2.6.3



[PATCH 2/2] drm/panel: add innolux,p079zca panel driver

2017-03-02 Thread Chris Zhong
Support Innolux P079ZCA 7.85" 768x1024 TFT LCD panel, it is a MIPI DSI
panel.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

 drivers/gpu/drm/panel/Kconfig |  11 +
 drivers/gpu/drm/panel/Makefile|   1 +
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 322 ++
 3 files changed, 334 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-innolux-p079zca.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 62aba97..99dd010 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -18,6 +18,17 @@ config DRM_PANEL_SIMPLE
  that it can be automatically turned off when the panel goes into a
  low power state.
 
+config DRM_PANEL_INNOLUX_P079ZCA
+   tristate "Innolux P079ZCA panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   depends on BACKLIGHT_CLASS_DEVICE
+   help
+ Say Y here if you want to enable support for Innolux P079ZCA
+ TFT-LCD modules. The panel has a 1024x768 resolution and uses
+ 24 bit RGB per pixel. It provides a MIPI DSI interface to
+ the host and has a built-in LED backlight.
+
 config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index a5c7ec0..bda2aa4 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
+obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
 obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
new file mode 100644
index 000..5d16705
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct innolux_panel {
+   struct drm_panel base;
+   struct mipi_dsi_device *link;
+
+   struct backlight_device *backlight;
+   struct regulator *supply;
+   struct gpio_desc *enable_gpio;
+
+   bool prepared;
+   bool enabled;
+};
+
+static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel)
+{
+   return container_of(panel, struct innolux_panel, base);
+}
+
+static int innolux_panel_disable(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->enabled)
+   return 0;
+
+   if (innolux->backlight) {
+   innolux->backlight->props.power = FB_BLANK_POWERDOWN;
+   backlight_update_status(innolux->backlight);
+   }
+
+   innolux->link->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+   err = mipi_dsi_dcs_set_display_off(innolux->link);
+   if (err < 0)
+   dev_err(panel->dev, "failed to set display off: %d\n", err);
+
+   innolux->enabled = false;
+
+   return 0;
+}
+
+static int innolux_panel_unprepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->prepared)
+   return 0;
+
+   innolux->link->mode_flags |= MIPI_DSI_MODE_LPM;
+
+   err = mipi_dsi_dcs_enter_sleep_mode(innolux->link);
+   if (err < 0)
+   dev_err(panel->dev, "failed to enter sleep mode: %d\n", err);
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+   msleep(120);
+
+   regulator_disable(innolux->supply);
+
+   innolux->prepared = false;
+
+   return 0;
+}
+
+static int innolux_panel_prepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (innolux->prepared)
+   return 0;
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+
+   err = regulator_enable(innolux->supply);
+   if (err < 0)
+   return err;
+
+   usleep_range(16000, 17000);
+   gpiod_set_value_cansleep(innolux->enable_gpio, 1);
+   usleep_range(15000, 16000);
+
+   innolux->link->mode_flags |= MIPI_DSI_MODE_LPM;
+
+   err = mipi_dsi_dcs_exit_sleep_mode(innolux->link);
+   if (err < 0

[PATCH 2/2] drm/panel: add innolux,p079zca panel driver

2017-03-02 Thread Chris Zhong
Support Innolux P079ZCA 7.85" 768x1024 TFT LCD panel, it is a MIPI DSI
panel.

Signed-off-by: Chris Zhong 
---

 drivers/gpu/drm/panel/Kconfig |  11 +
 drivers/gpu/drm/panel/Makefile|   1 +
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 322 ++
 3 files changed, 334 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-innolux-p079zca.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 62aba97..99dd010 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -18,6 +18,17 @@ config DRM_PANEL_SIMPLE
  that it can be automatically turned off when the panel goes into a
  low power state.
 
+config DRM_PANEL_INNOLUX_P079ZCA
+   tristate "Innolux P079ZCA panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   depends on BACKLIGHT_CLASS_DEVICE
+   help
+ Say Y here if you want to enable support for Innolux P079ZCA
+ TFT-LCD modules. The panel has a 1024x768 resolution and uses
+ 24 bit RGB per pixel. It provides a MIPI DSI interface to
+ the host and has a built-in LED backlight.
+
 config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index a5c7ec0..bda2aa4 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
+obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
 obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
new file mode 100644
index 000..5d16705
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct innolux_panel {
+   struct drm_panel base;
+   struct mipi_dsi_device *link;
+
+   struct backlight_device *backlight;
+   struct regulator *supply;
+   struct gpio_desc *enable_gpio;
+
+   bool prepared;
+   bool enabled;
+};
+
+static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel)
+{
+   return container_of(panel, struct innolux_panel, base);
+}
+
+static int innolux_panel_disable(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->enabled)
+   return 0;
+
+   if (innolux->backlight) {
+   innolux->backlight->props.power = FB_BLANK_POWERDOWN;
+   backlight_update_status(innolux->backlight);
+   }
+
+   innolux->link->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+   err = mipi_dsi_dcs_set_display_off(innolux->link);
+   if (err < 0)
+   dev_err(panel->dev, "failed to set display off: %d\n", err);
+
+   innolux->enabled = false;
+
+   return 0;
+}
+
+static int innolux_panel_unprepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (!innolux->prepared)
+   return 0;
+
+   innolux->link->mode_flags |= MIPI_DSI_MODE_LPM;
+
+   err = mipi_dsi_dcs_enter_sleep_mode(innolux->link);
+   if (err < 0)
+   dev_err(panel->dev, "failed to enter sleep mode: %d\n", err);
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+   msleep(120);
+
+   regulator_disable(innolux->supply);
+
+   innolux->prepared = false;
+
+   return 0;
+}
+
+static int innolux_panel_prepare(struct drm_panel *panel)
+{
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   int err;
+
+   if (innolux->prepared)
+   return 0;
+
+   gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+
+   err = regulator_enable(innolux->supply);
+   if (err < 0)
+   return err;
+
+   usleep_range(16000, 17000);
+   gpiod_set_value_cansleep(innolux->enable_gpio, 1);
+   usleep_range(15000, 16000);
+
+   innolux->link->mode_flags |= MIPI_DSI_MODE_LPM;
+
+   err = mipi_dsi_dcs_exit_sleep_mode(innolux->link);
+   if (err < 0) {
+   de

[PATCH 1/2] dt-bindings: Add INNOLUX P079ZCA panel bindings

2017-03-02 Thread Chris Zhong
The Innolux P079ZCA is a 7.85" panel with a 768X1024 resolution and
connected to DSI using four lanes.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
---

 .../bindings/display/panel/innolux,p079zca.txt | 22 ++
 1 file changed, 22 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt

diff --git 
a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt 
b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
new file mode 100644
index 000..c40c8e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
@@ -0,0 +1,22 @@
+Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,p079zca"
+- power-supply: phandle of the regulator that provides the supply voltage
+- enable-gpios: panel enable gpio
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+   _dsi {
+   panel {
+   compatible = "innolux,p079zca";
+   reg = <0>;
+   power-supply = <...>;
+   backlight = <>;
+   enable-gpios = < 13 GPIO_ACTIVE_HIGH>;
+   status = "okay";
+   };
+   };
-- 
2.6.3



[PATCH 1/2] dt-bindings: Add INNOLUX P079ZCA panel bindings

2017-03-02 Thread Chris Zhong
The Innolux P079ZCA is a 7.85" panel with a 768X1024 resolution and
connected to DSI using four lanes.

Signed-off-by: Chris Zhong 
---

 .../bindings/display/panel/innolux,p079zca.txt | 22 ++
 1 file changed, 22 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt

diff --git 
a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt 
b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
new file mode 100644
index 000..c40c8e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
@@ -0,0 +1,22 @@
+Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,p079zca"
+- power-supply: phandle of the regulator that provides the supply voltage
+- enable-gpios: panel enable gpio
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+   _dsi {
+   panel {
+   compatible = "innolux,p079zca";
+   reg = <0>;
+   power-supply = <...>;
+   backlight = <>;
+   enable-gpios = < 13 GPIO_ACTIVE_HIGH>;
+   status = "okay";
+   };
+   };
-- 
2.6.3



Re: [PATCH v4 00/23] drm/rockchip: MIPI fixes & improvements

2017-02-26 Thread Chris Zhong

Hi John

I have test this v4 series on my RK3399 board, it works well, thanks.

Tested-by: Chris Zhong<z...@rock-chips.com>


On 02/24/2017 08:54 PM, John Keeping wrote:

This version is mostly small changes in response to review comments from
Sean and Chris, the details are in the individual patches.

I decided to drop the final patch which adds support for MIPI read
commands because I'm not using that feature now and I can't easily test
it.  It's on the list if anyone wants to pick it up in the future.

Version 3 was posted here:
http://www.spinics.net/lists/dri-devel/msg130977.html

Thanks to Sean Paul and Chris Zhong for their review and testing of this
series.

John Keeping (23):
   drm/rockchip: dw-mipi-dsi: don't configure hardware in mode_set for
 MIPI
   drm/rockchip: dw-mipi-dsi: pass mode in where needed
   drm/rockchip: dw-mipi-dsi: remove mode_set hook
   drm/rockchip: dw-mipi-dsi: fix command header writes
   drm/rockchip: dw-mipi-dsi: fix generic packet status check
   drm/rockchip: dw-mipi-dsi: avoid out-of-bounds read on tx_buf
   drm/rockchip: dw-mipi-dsi: include bad value in error message
   drm/rockchip: dw-mipi-dsi: respect message flags
   drm/rockchip: dw-mipi-dsi: only request HS clock when required
   drm/rockchip: dw-mipi-dsi: don't assume buffer is aligned
   drm/rockchip: dw-mipi-dsi: prepare panel after phy init
   drm/rockchip: dw-mipi-dsi: allow commands in panel_disable
   drm/rockchip: dw-mipi-dsi: fix escape clock rate
   drm/rockchip: dw-mipi-dsi: ensure PHY is reset
   drm/rockchip: dw-mipi-dsi: configure PHY before enabling
   drm/rockchip: dw-mipi-dsi: properly configure PHY timing
   drm/rockchip: dw-mipi-dsi: improve PLL configuration
   drm/rockchip: dw-mipi-dsi: use specific poll helper
   drm/rockchip: dw-mipi-dsi: use positive check for N{H,V}SYNC
   drm/rockchip: vop: test for P{H,V}SYNC
   drm/rockchip: dw-mipi-dsi: defer probe if panel is not loaded
   drm/rockchip: dw-mipi-dsi: support non-burst modes
   drm/rockchip: dw-mipi-dsi: add reset control

  drivers/gpu/drm/rockchip/dw-mipi-dsi.c  | 325 +++-
  drivers/gpu/drm/rockchip/rockchip_drm_vop.c |   4 +-
  2 files changed, 220 insertions(+), 109 deletions(-)



--
Chris Zhong




Re: [PATCH v4 00/23] drm/rockchip: MIPI fixes & improvements

2017-02-26 Thread Chris Zhong

Hi John

I have test this v4 series on my RK3399 board, it works well, thanks.

Tested-by: Chris Zhong


On 02/24/2017 08:54 PM, John Keeping wrote:

This version is mostly small changes in response to review comments from
Sean and Chris, the details are in the individual patches.

I decided to drop the final patch which adds support for MIPI read
commands because I'm not using that feature now and I can't easily test
it.  It's on the list if anyone wants to pick it up in the future.

Version 3 was posted here:
http://www.spinics.net/lists/dri-devel/msg130977.html

Thanks to Sean Paul and Chris Zhong for their review and testing of this
series.

John Keeping (23):
   drm/rockchip: dw-mipi-dsi: don't configure hardware in mode_set for
 MIPI
   drm/rockchip: dw-mipi-dsi: pass mode in where needed
   drm/rockchip: dw-mipi-dsi: remove mode_set hook
   drm/rockchip: dw-mipi-dsi: fix command header writes
   drm/rockchip: dw-mipi-dsi: fix generic packet status check
   drm/rockchip: dw-mipi-dsi: avoid out-of-bounds read on tx_buf
   drm/rockchip: dw-mipi-dsi: include bad value in error message
   drm/rockchip: dw-mipi-dsi: respect message flags
   drm/rockchip: dw-mipi-dsi: only request HS clock when required
   drm/rockchip: dw-mipi-dsi: don't assume buffer is aligned
   drm/rockchip: dw-mipi-dsi: prepare panel after phy init
   drm/rockchip: dw-mipi-dsi: allow commands in panel_disable
   drm/rockchip: dw-mipi-dsi: fix escape clock rate
   drm/rockchip: dw-mipi-dsi: ensure PHY is reset
   drm/rockchip: dw-mipi-dsi: configure PHY before enabling
   drm/rockchip: dw-mipi-dsi: properly configure PHY timing
   drm/rockchip: dw-mipi-dsi: improve PLL configuration
   drm/rockchip: dw-mipi-dsi: use specific poll helper
   drm/rockchip: dw-mipi-dsi: use positive check for N{H,V}SYNC
   drm/rockchip: vop: test for P{H,V}SYNC
   drm/rockchip: dw-mipi-dsi: defer probe if panel is not loaded
   drm/rockchip: dw-mipi-dsi: support non-burst modes
   drm/rockchip: dw-mipi-dsi: add reset control

  drivers/gpu/drm/rockchip/dw-mipi-dsi.c  | 325 +++-
  drivers/gpu/drm/rockchip/rockchip_drm_vop.c |   4 +-
  2 files changed, 220 insertions(+), 109 deletions(-)



--
Chris Zhong




  1   2   3   4   5   6   7   8   9   10   >