Re: [v6-1,15/17] arm64: dts: rockchip: add isp0 node for rk3399

2018-03-11 Thread Shunqian Zheng

Ah, sorry, I used a wrong Message-Id in In-reply-to, please ignore this one.

Sorry about that.


On 2018年03月12日 11:37, Shunqian Zheng wrote:

rk3399 have two ISP, but we havn't test isp1, so just add isp0 at present.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Jacob Chen <jacob2.c...@rock-chips.com>
---
  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 18 ++
  1 file changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 2605118..5729786 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1614,6 +1614,24 @@
status = "disabled";
};
  
+	isp0: isp0@ff91 {

+   compatible = "rockchip,rk3399-cif-isp";
+   reg = <0x0 0xff91 0x0 0x4000>;
+   interrupts = ;
+   clocks = < SCLK_ISP0>,
+< ACLK_ISP0>, < ACLK_ISP0_WRAPPER>,
+< HCLK_ISP0>, < HCLK_ISP0_WRAPPER>;
+   clock-names = "clk_isp",
+ "aclk_isp", "aclk_isp_wrap",
+ "hclk_isp", "hclk_isp_wrap";
+   assigned-clocks = < SCLK_ISP0>, < ACLK_ISP0>;
+   assigned-clock-rates = <5>, <4>;
+
+   power-domains = < RK3399_PD_ISP0>;
+   iommus = <_mmu>;
+   status = "disabled";
+   };
+
isp0_mmu: iommu@ff914000 {
compatible = "rockchip,iommu";
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;





Re: [v6-1,15/17] arm64: dts: rockchip: add isp0 node for rk3399

2018-03-11 Thread Shunqian Zheng

Ah, sorry, I used a wrong Message-Id in In-reply-to, please ignore this one.

Sorry about that.


On 2018年03月12日 11:37, Shunqian Zheng wrote:

rk3399 have two ISP, but we havn't test isp1, so just add isp0 at present.

Signed-off-by: Shunqian Zheng 
Signed-off-by: Jacob Chen 
---
  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 18 ++
  1 file changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 2605118..5729786 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1614,6 +1614,24 @@
status = "disabled";
};
  
+	isp0: isp0@ff91 {

+   compatible = "rockchip,rk3399-cif-isp";
+   reg = <0x0 0xff91 0x0 0x4000>;
+   interrupts = ;
+   clocks = < SCLK_ISP0>,
+< ACLK_ISP0>, < ACLK_ISP0_WRAPPER>,
+< HCLK_ISP0>, < HCLK_ISP0_WRAPPER>;
+   clock-names = "clk_isp",
+ "aclk_isp", "aclk_isp_wrap",
+ "hclk_isp", "hclk_isp_wrap";
+   assigned-clocks = < SCLK_ISP0>, < ACLK_ISP0>;
+   assigned-clock-rates = <5>, <4>;
+
+   power-domains = < RK3399_PD_ISP0>;
+   iommus = <_mmu>;
+   status = "disabled";
+   };
+
isp0_mmu: iommu@ff914000 {
compatible = "rockchip,iommu";
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;





[PATCH v6-1,15/17] arm64: dts: rockchip: add isp0 node for rk3399

2018-03-11 Thread Shunqian Zheng
rk3399 have two ISP, but we havn't test isp1, so just add isp0 at present.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Jacob Chen <jacob2.c...@rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 2605118..5729786 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1614,6 +1614,24 @@
status = "disabled";
};
 
+   isp0: isp0@ff91 {
+   compatible = "rockchip,rk3399-cif-isp";
+   reg = <0x0 0xff91 0x0 0x4000>;
+   interrupts = ;
+   clocks = < SCLK_ISP0>,
+< ACLK_ISP0>, < ACLK_ISP0_WRAPPER>,
+< HCLK_ISP0>, < HCLK_ISP0_WRAPPER>;
+   clock-names = "clk_isp",
+ "aclk_isp", "aclk_isp_wrap",
+ "hclk_isp", "hclk_isp_wrap";
+   assigned-clocks = < SCLK_ISP0>, < ACLK_ISP0>;
+   assigned-clock-rates = <5>, <4>;
+
+   power-domains = < RK3399_PD_ISP0>;
+   iommus = <_mmu>;
+   status = "disabled";
+   };
+
isp0_mmu: iommu@ff914000 {
compatible = "rockchip,iommu";
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;
-- 
1.9.1



[PATCH v6-1,15/17] arm64: dts: rockchip: add isp0 node for rk3399

2018-03-11 Thread Shunqian Zheng
rk3399 have two ISP, but we havn't test isp1, so just add isp0 at present.

Signed-off-by: Shunqian Zheng 
Signed-off-by: Jacob Chen 
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 2605118..5729786 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1614,6 +1614,24 @@
status = "disabled";
};
 
+   isp0: isp0@ff91 {
+   compatible = "rockchip,rk3399-cif-isp";
+   reg = <0x0 0xff91 0x0 0x4000>;
+   interrupts = ;
+   clocks = < SCLK_ISP0>,
+< ACLK_ISP0>, < ACLK_ISP0_WRAPPER>,
+< HCLK_ISP0>, < HCLK_ISP0_WRAPPER>;
+   clock-names = "clk_isp",
+ "aclk_isp", "aclk_isp_wrap",
+ "hclk_isp", "hclk_isp_wrap";
+   assigned-clocks = < SCLK_ISP0>, < ACLK_ISP0>;
+   assigned-clock-rates = <5>, <4>;
+
+   power-domains = < RK3399_PD_ISP0>;
+   iommus = <_mmu>;
+   status = "disabled";
+   };
+
isp0_mmu: iommu@ff914000 {
compatible = "rockchip,iommu";
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;
-- 
1.9.1



[v6-1,15/17] arm64: dts: rockchip: add isp0 node for rk3399

2018-03-11 Thread Shunqian Zheng
rk3399 have two ISP, but we havn't test isp1, so just add isp0 at present.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Jacob Chen <jacob2.c...@rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 2605118..5729786 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1614,6 +1614,24 @@
status = "disabled";
};
 
+   isp0: isp0@ff91 {
+   compatible = "rockchip,rk3399-cif-isp";
+   reg = <0x0 0xff91 0x0 0x4000>;
+   interrupts = ;
+   clocks = < SCLK_ISP0>,
+< ACLK_ISP0>, < ACLK_ISP0_WRAPPER>,
+< HCLK_ISP0>, < HCLK_ISP0_WRAPPER>;
+   clock-names = "clk_isp",
+ "aclk_isp", "aclk_isp_wrap",
+ "hclk_isp", "hclk_isp_wrap";
+   assigned-clocks = < SCLK_ISP0>, < ACLK_ISP0>;
+   assigned-clock-rates = <5>, <4>;
+
+   power-domains = < RK3399_PD_ISP0>;
+   iommus = <_mmu>;
+   status = "disabled";
+   };
+
isp0_mmu: iommu@ff914000 {
compatible = "rockchip,iommu";
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;
-- 
1.9.1



[v6-1,15/17] arm64: dts: rockchip: add isp0 node for rk3399

2018-03-11 Thread Shunqian Zheng
rk3399 have two ISP, but we havn't test isp1, so just add isp0 at present.

Signed-off-by: Shunqian Zheng 
Signed-off-by: Jacob Chen 
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 2605118..5729786 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1614,6 +1614,24 @@
status = "disabled";
};
 
+   isp0: isp0@ff91 {
+   compatible = "rockchip,rk3399-cif-isp";
+   reg = <0x0 0xff91 0x0 0x4000>;
+   interrupts = ;
+   clocks = < SCLK_ISP0>,
+< ACLK_ISP0>, < ACLK_ISP0_WRAPPER>,
+< HCLK_ISP0>, < HCLK_ISP0_WRAPPER>;
+   clock-names = "clk_isp",
+ "aclk_isp", "aclk_isp_wrap",
+ "hclk_isp", "hclk_isp_wrap";
+   assigned-clocks = < SCLK_ISP0>, < ACLK_ISP0>;
+   assigned-clock-rates = <5>, <4>;
+
+   power-domains = < RK3399_PD_ISP0>;
+   iommus = <_mmu>;
+   status = "disabled";
+   };
+
isp0_mmu: iommu@ff914000 {
compatible = "rockchip,iommu";
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;
-- 
1.9.1



[PATCH] arm64: dts: rockchip: assign clock rate for ACLK_VIO

2018-03-11 Thread Shunqian Zheng
The ACLK_VIO is a parent clock used by a several children,
its suggested clock rate is 400MHz. Right now it gets 400MHz
because it sources from CPLL(800M) and divides by 2 after reset.
It's good not to rely on default values like this, so let's
explicitly set it.
NOTE: it's expected that at least one board may override cru node and
set the CPLL to 1.6 GHz. On that board it will be very important to be
explicit about aclk-vio being 400 MHz.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 6 --
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 6 --
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
index 199a511..7d8d5de 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
@@ -580,7 +580,8 @@
< PCLK_PERIHP>,
< ACLK_PERILP0>, < HCLK_PERILP0>,
< PCLK_PERILP0>, < ACLK_CCI>,
-   < HCLK_PERILP1>, < PCLK_PERILP1>;
+   < HCLK_PERILP1>, < PCLK_PERILP1>,
+   < ACLK_VIO>;
assigned-clock-rates =
<6>, <8>,
<10>,
@@ -588,7 +589,8 @@
<3750>,
<1>, <1>,
<5000>, <8>,
-   <1>, <5000>;
+   <1>, <5000>,
+   <4>;
 };
 
 _phy {
diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index d79e9b3..91ee951 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1259,7 +1259,8 @@
< PCLK_PERIHP>,
< ACLK_PERILP0>, < HCLK_PERILP0>,
< PCLK_PERILP0>, < ACLK_CCI>,
-   < HCLK_PERILP1>, < PCLK_PERILP1>;
+   < HCLK_PERILP1>, < PCLK_PERILP1>,
+   < ACLK_VIO>;
assigned-clock-rates =
 <59400>,  <8>,
<10>,
@@ -1267,7 +1268,8 @@
  <3750>,
 <1>,  <1>,
  <5000>, <6>,
-<1>,   <5000>;
+<1>,   <5000>,
+<4>;
};
 
grf: syscon@ff77 {
-- 
1.9.1



[PATCH] arm64: dts: rockchip: assign clock rate for ACLK_VIO

2018-03-11 Thread Shunqian Zheng
The ACLK_VIO is a parent clock used by a several children,
its suggested clock rate is 400MHz. Right now it gets 400MHz
because it sources from CPLL(800M) and divides by 2 after reset.
It's good not to rely on default values like this, so let's
explicitly set it.
NOTE: it's expected that at least one board may override cru node and
set the CPLL to 1.6 GHz. On that board it will be very important to be
explicit about aclk-vio being 400 MHz.

Signed-off-by: Shunqian Zheng 
---
 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 6 --
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 6 --
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
index 199a511..7d8d5de 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
@@ -580,7 +580,8 @@
< PCLK_PERIHP>,
< ACLK_PERILP0>, < HCLK_PERILP0>,
< PCLK_PERILP0>, < ACLK_CCI>,
-   < HCLK_PERILP1>, < PCLK_PERILP1>;
+   < HCLK_PERILP1>, < PCLK_PERILP1>,
+   < ACLK_VIO>;
assigned-clock-rates =
<6>, <8>,
<10>,
@@ -588,7 +589,8 @@
<3750>,
<1>, <1>,
<5000>, <8>,
-   <1>, <5000>;
+   <1>, <5000>,
+   <4>;
 };
 
 _phy {
diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index d79e9b3..91ee951 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1259,7 +1259,8 @@
< PCLK_PERIHP>,
< ACLK_PERILP0>, < HCLK_PERILP0>,
< PCLK_PERILP0>, < ACLK_CCI>,
-   < HCLK_PERILP1>, < PCLK_PERILP1>;
+   < HCLK_PERILP1>, < PCLK_PERILP1>,
+   < ACLK_VIO>;
assigned-clock-rates =
 <59400>,  <8>,
<10>,
@@ -1267,7 +1268,8 @@
  <3750>,
 <1>,  <1>,
  <5000>, <6>,
-<1>,   <5000>;
+<1>,   <5000>,
+<4>;
};
 
grf: syscon@ff77 {
-- 
1.9.1



[PATCH v5 01/16] media: videodev2.h, v4l2-ioctl: add rkisp1 meta buffer format

2017-12-29 Thread Shunqian Zheng
Add the Rockchip ISP1 specific processing parameter format
V4L2_META_FMT_RK_ISP1_PARAMS and metadata format
V4L2_META_FMT_RK_ISP1_STAT_3A for 3A.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Jacob Chen <jacob2.c...@rock-chips.com>
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 2 ++
 include/uapi/linux/videodev2.h   | 4 
 2 files changed, 6 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 7961499..035fd22 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1246,6 +1246,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_TCH_FMT_TU08: descr = "8-bit unsigned touch data"; 
break;
case V4L2_META_FMT_VSP1_HGO:descr = "R-Car VSP1 1-D Histogram"; 
break;
case V4L2_META_FMT_VSP1_HGT:descr = "R-Car VSP1 2-D Histogram"; 
break;
+   case V4L2_META_FMT_RK_ISP1_PARAMS:  descr = "Rockchip ISP1 3A 
params"; break;
+   case V4L2_META_FMT_RK_ISP1_STAT_3A: descr = "Rockchip ISP1 3A 
statistics"; break;
 
default:
/* Compressed formats */
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 1c095b5..c023c3a 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -689,6 +689,10 @@ struct v4l2_pix_format {
 #define V4L2_META_FMT_VSP1_HGOv4l2_fourcc('V', 'S', 'P', 'H') /* R-Car 
VSP1 1-D Histogram */
 #define V4L2_META_FMT_VSP1_HGTv4l2_fourcc('V', 'S', 'P', 'T') /* R-Car 
VSP1 2-D Histogram */
 
+/* Vendor specific - used for IPU3 camera sub-system */
+#define V4L2_META_FMT_RK_ISP1_PARAMS   v4l2_fourcc('R', 'K', '1', 'P') /* 
Rockchip ISP1 params */
+#define V4L2_META_FMT_RK_ISP1_STAT_3A  v4l2_fourcc('R', 'K', '1', 'S') /* 
Rockchip ISP1 3A statistics */
+
 /* priv field value to indicates that subsequent fields are valid. */
 #define V4L2_PIX_FMT_PRIV_MAGIC0xfeedcafe
 
-- 
1.9.1



[PATCH v5 01/16] media: videodev2.h, v4l2-ioctl: add rkisp1 meta buffer format

2017-12-29 Thread Shunqian Zheng
Add the Rockchip ISP1 specific processing parameter format
V4L2_META_FMT_RK_ISP1_PARAMS and metadata format
V4L2_META_FMT_RK_ISP1_STAT_3A for 3A.

Signed-off-by: Shunqian Zheng 
Signed-off-by: Jacob Chen 
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 2 ++
 include/uapi/linux/videodev2.h   | 4 
 2 files changed, 6 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 7961499..035fd22 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1246,6 +1246,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_TCH_FMT_TU08: descr = "8-bit unsigned touch data"; 
break;
case V4L2_META_FMT_VSP1_HGO:descr = "R-Car VSP1 1-D Histogram"; 
break;
case V4L2_META_FMT_VSP1_HGT:descr = "R-Car VSP1 2-D Histogram"; 
break;
+   case V4L2_META_FMT_RK_ISP1_PARAMS:  descr = "Rockchip ISP1 3A 
params"; break;
+   case V4L2_META_FMT_RK_ISP1_STAT_3A: descr = "Rockchip ISP1 3A 
statistics"; break;
 
default:
/* Compressed formats */
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 1c095b5..c023c3a 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -689,6 +689,10 @@ struct v4l2_pix_format {
 #define V4L2_META_FMT_VSP1_HGOv4l2_fourcc('V', 'S', 'P', 'H') /* R-Car 
VSP1 1-D Histogram */
 #define V4L2_META_FMT_VSP1_HGTv4l2_fourcc('V', 'S', 'P', 'T') /* R-Car 
VSP1 2-D Histogram */
 
+/* Vendor specific - used for IPU3 camera sub-system */
+#define V4L2_META_FMT_RK_ISP1_PARAMS   v4l2_fourcc('R', 'K', '1', 'P') /* 
Rockchip ISP1 params */
+#define V4L2_META_FMT_RK_ISP1_STAT_3A  v4l2_fourcc('R', 'K', '1', 'S') /* 
Rockchip ISP1 3A statistics */
+
 /* priv field value to indicates that subsequent fields are valid. */
 #define V4L2_PIX_FMT_PRIV_MAGIC0xfeedcafe
 
-- 
1.9.1



[PATCH v5 05/16] media: rkisp1: add Rockchip ISP1 subdev driver

2017-12-29 Thread Shunqian Zheng
From: Jacob Chen <jacob2.c...@rock-chips.com>

Add the subdev driver for rockchip isp1.

Signed-off-by: Jacob Chen <jacob2.c...@rock-chips.com>
Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Yichong Zhong <z...@rock-chips.com>
Signed-off-by: Jacob Chen <c...@rock-chips.com>
Signed-off-by: Eddie Cai <eddie.cai.li...@gmail.com>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Signed-off-by: Allon Huang <allon.hu...@rock-chips.com>
Signed-off-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/media/platform/rockchip/isp1/rkisp1.c | 1205 +
 drivers/media/platform/rockchip/isp1/rkisp1.h |  132 +++
 2 files changed, 1337 insertions(+)
 create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.c
 create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.h

diff --git a/drivers/media/platform/rockchip/isp1/rkisp1.c 
b/drivers/media/platform/rockchip/isp1/rkisp1.c
new file mode 100644
index 000..2656c5e
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/rkisp1.c
@@ -0,0 +1,1205 @@
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *  - Redistributions of source code must retain the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer in the documentation and/or other materials
+ *provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "common.h"
+#include "regs.h"
+
+#define CIF_ISP_INPUT_W_MAX4032
+#define CIF_ISP_INPUT_H_MAX3024
+#define CIF_ISP_INPUT_W_MIN32
+#define CIF_ISP_INPUT_H_MIN32
+#define CIF_ISP_OUTPUT_W_MAX   CIF_ISP_INPUT_W_MAX
+#define CIF_ISP_OUTPUT_H_MAX   CIF_ISP_INPUT_H_MAX
+#define CIF_ISP_OUTPUT_W_MIN   CIF_ISP_INPUT_W_MIN
+#define CIF_ISP_OUTPUT_H_MIN   CIF_ISP_INPUT_H_MIN
+
+/*
+ * NOTE: MIPI controller and input MUX are also configured in this file,
+ * because ISP Subdev is not only describe ISP submodule(input size,format, 
output size, format),
+ * but also a virtual route device.
+ */
+
+/*
+ * There are many variables named with format/frame in below code,
+ * please see here for their meaning.
+ *
+ * Cropping regions of ISP
+ *
+ * +-+
+ * | Sensor image|
+ * | +---+   |
+ * | | ISP_ACQ (for black level) |   |
+ * | | in_frm|   |
+ * | | ++|   |
+ * | | |ISP_OUT ||   |
+ * | | |in_crop ||   |
+ * | | |+-+ ||   |
+ * | | ||   ISP_IS| ||   |
+ * | | ||   rkisp1_isp_subdev: out_crop   | ||   |
+ * | | |+-+ ||   |
+ * | | ++|   |
+ * | +---+   |
+ * +-+
+ */
+
+static inline struct rkisp1_device *sd_to_isp_dev(struct v4l2_subdev *sd)
+{
+   return container_of(sd->v4l2_dev, struct rkisp1_device, v4l2_dev);
+}
+
+/* Get sensor by enabled media link */
+static struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd)
+{
+   struct media_pad *local;
+   struct media_entity *sensor_me;
+
+   local = >entity.pads[RKISP1_ISP_PAD_SINK];
+   sensor_me = media_entity_remote_pad(local)->entity;
+
+   return media_entity_to_v4l2_subd

[PATCH v5 05/16] media: rkisp1: add Rockchip ISP1 subdev driver

2017-12-29 Thread Shunqian Zheng
From: Jacob Chen 

Add the subdev driver for rockchip isp1.

Signed-off-by: Jacob Chen 
Signed-off-by: Shunqian Zheng 
Signed-off-by: Yichong Zhong 
Signed-off-by: Jacob Chen 
Signed-off-by: Eddie Cai 
Signed-off-by: Jeffy Chen 
Signed-off-by: Allon Huang 
Signed-off-by: Tomasz Figa 
---
 drivers/media/platform/rockchip/isp1/rkisp1.c | 1205 +
 drivers/media/platform/rockchip/isp1/rkisp1.h |  132 +++
 2 files changed, 1337 insertions(+)
 create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.c
 create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.h

diff --git a/drivers/media/platform/rockchip/isp1/rkisp1.c 
b/drivers/media/platform/rockchip/isp1/rkisp1.c
new file mode 100644
index 000..2656c5e
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/rkisp1.c
@@ -0,0 +1,1205 @@
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *  - Redistributions of source code must retain the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer in the documentation and/or other materials
+ *provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "common.h"
+#include "regs.h"
+
+#define CIF_ISP_INPUT_W_MAX4032
+#define CIF_ISP_INPUT_H_MAX3024
+#define CIF_ISP_INPUT_W_MIN32
+#define CIF_ISP_INPUT_H_MIN32
+#define CIF_ISP_OUTPUT_W_MAX   CIF_ISP_INPUT_W_MAX
+#define CIF_ISP_OUTPUT_H_MAX   CIF_ISP_INPUT_H_MAX
+#define CIF_ISP_OUTPUT_W_MIN   CIF_ISP_INPUT_W_MIN
+#define CIF_ISP_OUTPUT_H_MIN   CIF_ISP_INPUT_H_MIN
+
+/*
+ * NOTE: MIPI controller and input MUX are also configured in this file,
+ * because ISP Subdev is not only describe ISP submodule(input size,format, 
output size, format),
+ * but also a virtual route device.
+ */
+
+/*
+ * There are many variables named with format/frame in below code,
+ * please see here for their meaning.
+ *
+ * Cropping regions of ISP
+ *
+ * +-+
+ * | Sensor image|
+ * | +---+   |
+ * | | ISP_ACQ (for black level) |   |
+ * | | in_frm|   |
+ * | | ++|   |
+ * | | |ISP_OUT ||   |
+ * | | |in_crop ||   |
+ * | | |+-+ ||   |
+ * | | ||   ISP_IS| ||   |
+ * | | ||   rkisp1_isp_subdev: out_crop   | ||   |
+ * | | |+-+ ||   |
+ * | | ++|   |
+ * | +---+   |
+ * +-+
+ */
+
+static inline struct rkisp1_device *sd_to_isp_dev(struct v4l2_subdev *sd)
+{
+   return container_of(sd->v4l2_dev, struct rkisp1_device, v4l2_dev);
+}
+
+/* Get sensor by enabled media link */
+static struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd)
+{
+   struct media_pad *local;
+   struct media_entity *sensor_me;
+
+   local = >entity.pads[RKISP1_ISP_PAD_SINK];
+   sensor_me = media_entity_remote_pad(local)->entity;
+
+   return media_entity_to_v4l2_subdev(sensor_me);
+}
+
+static struct rkisp1_sensor_info *sd_to_sensor(struct rkisp1_device *dev,
+  struct v4l2_subdev *sd)
+{
+   int i;
+
+   for (i = 0; i < dev->num_sensors; ++i)
+   if (dev->sensors[i].sd 

[PATCH v5 09/16] media: rkisp1: add rockchip isp1 core driver

2017-12-29 Thread Shunqian Zheng
From: Jacob Chen <jacob2.c...@rock-chips.com>

Add the core driver for rockchip isp1.

Signed-off-by: Jacob Chen <jacob2.c...@rock-chips.com>
Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Yichong Zhong <z...@rock-chips.com>
Signed-off-by: Jacob Chen <c...@rock-chips.com>
Signed-off-by: Eddie Cai <eddie.cai.li...@gmail.com>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Signed-off-by: Allon Huang <allon.hu...@rock-chips.com>
Signed-off-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/media/platform/Kconfig|  10 +
 drivers/media/platform/Makefile   |   1 +
 drivers/media/platform/rockchip/isp1/Makefile |   8 +
 drivers/media/platform/rockchip/isp1/common.h | 137 ++
 drivers/media/platform/rockchip/isp1/dev.c| 653 ++
 drivers/media/platform/rockchip/isp1/dev.h| 120 +
 6 files changed, 929 insertions(+)
 create mode 100644 drivers/media/platform/rockchip/isp1/Makefile
 create mode 100644 drivers/media/platform/rockchip/isp1/common.h
 create mode 100644 drivers/media/platform/rockchip/isp1/dev.c
 create mode 100644 drivers/media/platform/rockchip/isp1/dev.h

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index fd0c998..062fffc 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -117,6 +117,16 @@ config VIDEO_QCOM_CAMSS
select VIDEOBUF2_DMA_SG
select V4L2_FWNODE
 
+config VIDEO_ROCKCHIP_ISP1
+   tristate "Rockchip Image Signal Processing v1 Unit driver"
+   depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+   depends on ARCH_ROCKCHIP || COMPILE_TEST
+   select VIDEOBUF2_DMA_CONTIG
+   select V4L2_FWNODE
+   default n
+   ---help---
+ Support for ISP1 on the rockchip SoC.
+
 config VIDEO_S3C_CAMIF
tristate "Samsung S3C24XX/S3C64XX SoC Camera Interface driver"
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 003b0bb..d235908 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_RENESAS_FDP1)  += rcar_fdp1.o
 obj-$(CONFIG_VIDEO_RENESAS_JPU)+= rcar_jpu.o
 obj-$(CONFIG_VIDEO_RENESAS_VSP1)   += vsp1/
 
+obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1)  += rockchip/isp1/
 obj-$(CONFIG_VIDEO_ROCKCHIP_RGA)   += rockchip/rga/
 
 obj-y  += omap/
diff --git a/drivers/media/platform/rockchip/isp1/Makefile 
b/drivers/media/platform/rockchip/isp1/Makefile
new file mode 100644
index 000..18af648
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/Makefile
@@ -0,0 +1,8 @@
+obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) +=   video_rkisp1.o
+video_rkisp1-objs +=   rkisp1.o \
+   dev.o \
+   regs.o \
+   isp_stats.o \
+   isp_params.o \
+   mipi_dphy_sy.o \
+   capture.o
diff --git a/drivers/media/platform/rockchip/isp1/common.h 
b/drivers/media/platform/rockchip/isp1/common.h
new file mode 100644
index 000..1adfb90
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/common.h
@@ -0,0 +1,137 @@
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *  - Redistributions of source code must retain the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer in the documentation and/or other materials
+ *provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _RKISP1_COMMON_H
+#define _RKISP1_COMMON_H
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#i

[PATCH v5 09/16] media: rkisp1: add rockchip isp1 core driver

2017-12-29 Thread Shunqian Zheng
From: Jacob Chen 

Add the core driver for rockchip isp1.

Signed-off-by: Jacob Chen 
Signed-off-by: Shunqian Zheng 
Signed-off-by: Yichong Zhong 
Signed-off-by: Jacob Chen 
Signed-off-by: Eddie Cai 
Signed-off-by: Jeffy Chen 
Signed-off-by: Allon Huang 
Signed-off-by: Tomasz Figa 
---
 drivers/media/platform/Kconfig|  10 +
 drivers/media/platform/Makefile   |   1 +
 drivers/media/platform/rockchip/isp1/Makefile |   8 +
 drivers/media/platform/rockchip/isp1/common.h | 137 ++
 drivers/media/platform/rockchip/isp1/dev.c| 653 ++
 drivers/media/platform/rockchip/isp1/dev.h| 120 +
 6 files changed, 929 insertions(+)
 create mode 100644 drivers/media/platform/rockchip/isp1/Makefile
 create mode 100644 drivers/media/platform/rockchip/isp1/common.h
 create mode 100644 drivers/media/platform/rockchip/isp1/dev.c
 create mode 100644 drivers/media/platform/rockchip/isp1/dev.h

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index fd0c998..062fffc 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -117,6 +117,16 @@ config VIDEO_QCOM_CAMSS
select VIDEOBUF2_DMA_SG
select V4L2_FWNODE
 
+config VIDEO_ROCKCHIP_ISP1
+   tristate "Rockchip Image Signal Processing v1 Unit driver"
+   depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+   depends on ARCH_ROCKCHIP || COMPILE_TEST
+   select VIDEOBUF2_DMA_CONTIG
+   select V4L2_FWNODE
+   default n
+   ---help---
+ Support for ISP1 on the rockchip SoC.
+
 config VIDEO_S3C_CAMIF
tristate "Samsung S3C24XX/S3C64XX SoC Camera Interface driver"
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 003b0bb..d235908 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_RENESAS_FDP1)  += rcar_fdp1.o
 obj-$(CONFIG_VIDEO_RENESAS_JPU)+= rcar_jpu.o
 obj-$(CONFIG_VIDEO_RENESAS_VSP1)   += vsp1/
 
+obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1)  += rockchip/isp1/
 obj-$(CONFIG_VIDEO_ROCKCHIP_RGA)   += rockchip/rga/
 
 obj-y  += omap/
diff --git a/drivers/media/platform/rockchip/isp1/Makefile 
b/drivers/media/platform/rockchip/isp1/Makefile
new file mode 100644
index 000..18af648
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/Makefile
@@ -0,0 +1,8 @@
+obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) +=   video_rkisp1.o
+video_rkisp1-objs +=   rkisp1.o \
+   dev.o \
+   regs.o \
+   isp_stats.o \
+   isp_params.o \
+   mipi_dphy_sy.o \
+   capture.o
diff --git a/drivers/media/platform/rockchip/isp1/common.h 
b/drivers/media/platform/rockchip/isp1/common.h
new file mode 100644
index 000..1adfb90
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/common.h
@@ -0,0 +1,137 @@
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *  - Redistributions of source code must retain the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer in the documentation and/or other materials
+ *provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _RKISP1_COMMON_H
+#define _RKISP1_COMMON_H
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RKISP1_DEFAULT_WIDTH   800
+#define RKISP1_DEFAULT_HEIGHT  600
+
+#define RKISP1_MAX_STREAM  2
+#define RKISP1_STREAM_SP   0
+#define RKISP1_STREAM_MP   1
+
+#define RKISP1_PLANE_Y 0
+#de

[PATCH v5 10/16] dt-bindings: Document the Rockchip ISP1 bindings

2017-12-29 Thread Shunqian Zheng
From: Jacob Chen 

Add DT bindings documentation for Rockchip ISP1

Signed-off-by: Jacob Chen 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/media/rockchip-isp1.txt| 69 ++
 1 file changed, 69 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/rockchip-isp1.txt

diff --git a/Documentation/devicetree/bindings/media/rockchip-isp1.txt 
b/Documentation/devicetree/bindings/media/rockchip-isp1.txt
new file mode 100644
index 000..4631a4b
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/rockchip-isp1.txt
@@ -0,0 +1,69 @@
+Rockchip SoC Image Signal Processing unit v1
+--
+
+Rockchip ISP1 is the Camera interface for the Rockchip series of SoCs
+which contains image processing, scaling, and compression funcitons.
+
+Required properties:
+- compatible: value should be one of the following
+   "rockchip,rk3288-cif-isp";
+   "rockchip,rk3399-cif-isp";
+- reg : offset and length of the register set for the device.
+- interrupts: should contain ISP interrupt.
+- clocks: phandle to the required clocks.
+- clock-names: required clock name.
+- iommus: required a iommu node.
+
+port node
+---
+
+The device node should contain one 'port' child node with child 'endpoint'
+nodes, according to the bindings defined in Documentation/devicetree/bindings/
+media/video-interfaces.txt.
+
+- endpoint(parallel):
+   - remote-endpoint: Connecting to a sensor with a parallel video bus.
+   - parallel_bus properties: Refer to Documentation/devicetree/bindings/
+   media/video-interfaces.txt.
+- endpoint(mipi):
+   - remote-endpoint: Connecting to Rockchip MIPI-DPHY,
+   which is defined in rockchip-mipi-dphy.txt.
+
+The port node must contain at least one endpoint, either parallel or mipi.
+It could have multiple endpoints, but please note the hardware don't support
+two sensors work at a time, they are supposed to work asynchronously.
+
+Device node example
+---
+
+   isp0: isp0@ff91 {
+   compatible = "rockchip,rk3399-cif-isp";
+   reg = <0x0 0xff91 0x0 0x4000>;
+   interrupts = ;
+   clocks = < SCLK_ISP0>,
+< ACLK_ISP0>, < ACLK_ISP0_WRAPPER>,
+< HCLK_ISP0>, < HCLK_ISP0_WRAPPER>;
+   clock-names = "clk_isp",
+ "aclk_isp", "aclk_isp_wrap",
+ "hclk_isp", "hclk_isp_wrap";
+   power-domains = < RK3399_PD_ISP0>;
+   iommus = <_mmu>;
+
+   port {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   /* mipi */
+   isp0_mipi_in: endpoint@0 {
+   reg = <0>;
+   remote-endpoint = <_rx0_out>;
+   };
+
+   /* parallel */
+   isp0_parallel_in: endpoint@1 {
+   reg = <1>;
+   remote-endpoint = <_out>;
+   bus-width = <8>;
+   };
+   };
+   };
-- 
1.9.1



[PATCH v5 10/16] dt-bindings: Document the Rockchip ISP1 bindings

2017-12-29 Thread Shunqian Zheng
From: Jacob Chen 

Add DT bindings documentation for Rockchip ISP1

Signed-off-by: Jacob Chen 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/media/rockchip-isp1.txt| 69 ++
 1 file changed, 69 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/rockchip-isp1.txt

diff --git a/Documentation/devicetree/bindings/media/rockchip-isp1.txt 
b/Documentation/devicetree/bindings/media/rockchip-isp1.txt
new file mode 100644
index 000..4631a4b
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/rockchip-isp1.txt
@@ -0,0 +1,69 @@
+Rockchip SoC Image Signal Processing unit v1
+--
+
+Rockchip ISP1 is the Camera interface for the Rockchip series of SoCs
+which contains image processing, scaling, and compression funcitons.
+
+Required properties:
+- compatible: value should be one of the following
+   "rockchip,rk3288-cif-isp";
+   "rockchip,rk3399-cif-isp";
+- reg : offset and length of the register set for the device.
+- interrupts: should contain ISP interrupt.
+- clocks: phandle to the required clocks.
+- clock-names: required clock name.
+- iommus: required a iommu node.
+
+port node
+---
+
+The device node should contain one 'port' child node with child 'endpoint'
+nodes, according to the bindings defined in Documentation/devicetree/bindings/
+media/video-interfaces.txt.
+
+- endpoint(parallel):
+   - remote-endpoint: Connecting to a sensor with a parallel video bus.
+   - parallel_bus properties: Refer to Documentation/devicetree/bindings/
+   media/video-interfaces.txt.
+- endpoint(mipi):
+   - remote-endpoint: Connecting to Rockchip MIPI-DPHY,
+   which is defined in rockchip-mipi-dphy.txt.
+
+The port node must contain at least one endpoint, either parallel or mipi.
+It could have multiple endpoints, but please note the hardware don't support
+two sensors work at a time, they are supposed to work asynchronously.
+
+Device node example
+---
+
+   isp0: isp0@ff91 {
+   compatible = "rockchip,rk3399-cif-isp";
+   reg = <0x0 0xff91 0x0 0x4000>;
+   interrupts = ;
+   clocks = < SCLK_ISP0>,
+< ACLK_ISP0>, < ACLK_ISP0_WRAPPER>,
+< HCLK_ISP0>, < HCLK_ISP0_WRAPPER>;
+   clock-names = "clk_isp",
+ "aclk_isp", "aclk_isp_wrap",
+ "hclk_isp", "hclk_isp_wrap";
+   power-domains = < RK3399_PD_ISP0>;
+   iommus = <_mmu>;
+
+   port {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   /* mipi */
+   isp0_mipi_in: endpoint@0 {
+   reg = <0>;
+   remote-endpoint = <_rx0_out>;
+   };
+
+   /* parallel */
+   isp0_parallel_in: endpoint@1 {
+   reg = <1>;
+   remote-endpoint = <_out>;
+   bus-width = <8>;
+   };
+   };
+   };
-- 
1.9.1



[PATCH v5 11/16] dt-bindings: Document the Rockchip MIPI RX D-PHY bindings

2017-12-29 Thread Shunqian Zheng
From: Jacob Chen 

Add DT bindings documentation for Rockchip MIPI D-PHY RX

Signed-off-by: Jacob Chen 
Reviewed-by: Rob Herring 
---
 .../bindings/media/rockchip-mipi-dphy.txt  | 88 ++
 1 file changed, 88 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt

diff --git a/Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt 
b/Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt
new file mode 100644
index 000..0571d7f
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt
@@ -0,0 +1,88 @@
+Rockchip SoC MIPI RX D-PHY
+-
+
+Required properties:
+- compatible: value should be one of the following
+   "rockchip,rk3288-mipi-dphy"
+   "rockchip,rk3399-mipi-dphy"
+- clocks : list of clock specifiers, corresponding to entries in
+   clock-names property;
+- clock-names: required clock name.
+
+MIPI RX0 D-PHY use registers in "general register files", it
+should be a child of the GRF.
+MIPI TXRX D-PHY have its own registers, it must have a reg property.
+
+Optional properties:
+- reg: offset and length of the register set for the device.
+
+port node
+---
+
+The device node should contain two 'port' child nodes, according to the 
bindings
+defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+The first port show the sensors connected in this mipi-dphy.
+- endpoint:
+   - remote-endpoint: Linked to a sensor with a MIPI CSI-2 video bus.
+   - data-lanes : (required) an array specifying active physical MIPI-CSI2
+   data input lanes and their mapping to logical lanes; the
+   D-PHY can't reroute lanes, so the array's content should
+   be consecutive and only its length is meaningful.
+
+The port node must contain at least one endpoint. It could have multiple 
endpoints
+linked to different sensors, but please note that they are not supposed to be
+activated at the same time.
+
+The second port should be connected to isp node.
+- endpoint:
+   - remote-endpoint:  Linked to Rockchip ISP1, which is defined
+   in rockchip-isp1.txt.
+
+Device node example
+---
+
+grf: syscon@ff77 {
+   compatible = "rockchip,rk3288-grf", "syscon", "simple-mfd";
+
+...
+
+   mipi_dphy_rx0: mipi-dphy-rx0 {
+   compatible = "rockchip,rk3399-mipi-dphy";
+   clocks = < SCLK_MIPIDPHY_REF>,
+   < SCLK_DPHY_RX0_CFG>,
+   < PCLK_VIO_GRF>;
+   clock-names = "dphy-ref", "dphy-cfg", "grf";
+   power-domains = < RK3399_PD_VIO>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port@0 {
+   reg = <0>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   mipi_in_wcam: endpoint@0 {
+   reg = <0>;
+   remote-endpoint = <_out>;
+   data-lanes = <1 2>;
+   };
+   mipi_in_ucam: endpoint@1 {
+   reg = <1>;
+   remote-endpoint = <_out>;
+   data-lanes = <1>;
+   };
+   };
+
+   port@1 {
+   reg = <1>;
+
+   dphy_rx0_out: endpoint {
+   remote-endpoint = <_mipi_in>;
+   };
+   };
+   };
+   };
+};
-- 
1.9.1



[PATCH v5 14/16] arm64: dts: rockchip: add isp0 node for rk3399

2017-12-29 Thread Shunqian Zheng
rk3399 have two ISP, but we havn't test isp1, so just add isp0 at present.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Jacob Chen <jacob2.c...@rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index d340b58a..66a912f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1588,6 +1588,21 @@
status = "disabled";
};
 
+   isp0: isp0@ff91 {
+   compatible = "rockchip,rk3399-cif-isp";
+   reg = <0x0 0xff91 0x0 0x4000>;
+   interrupts = ;
+   clocks = < SCLK_ISP0>,
+< ACLK_ISP0>, < ACLK_ISP0_WRAPPER>,
+< HCLK_ISP0>, < HCLK_ISP0_WRAPPER>;
+   clock-names = "clk_isp",
+ "aclk_isp", "aclk_isp_wrap",
+ "hclk_isp", "hclk_isp_wrap";
+   power-domains = < RK3399_PD_ISP0>;
+   iommus = <_mmu>;
+   status = "disabled";
+   };
+
isp0_mmu: iommu@ff914000 {
compatible = "rockchip,iommu";
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;
-- 
1.9.1



[PATCH v5 11/16] dt-bindings: Document the Rockchip MIPI RX D-PHY bindings

2017-12-29 Thread Shunqian Zheng
From: Jacob Chen 

Add DT bindings documentation for Rockchip MIPI D-PHY RX

Signed-off-by: Jacob Chen 
Reviewed-by: Rob Herring 
---
 .../bindings/media/rockchip-mipi-dphy.txt  | 88 ++
 1 file changed, 88 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt

diff --git a/Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt 
b/Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt
new file mode 100644
index 000..0571d7f
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt
@@ -0,0 +1,88 @@
+Rockchip SoC MIPI RX D-PHY
+-
+
+Required properties:
+- compatible: value should be one of the following
+   "rockchip,rk3288-mipi-dphy"
+   "rockchip,rk3399-mipi-dphy"
+- clocks : list of clock specifiers, corresponding to entries in
+   clock-names property;
+- clock-names: required clock name.
+
+MIPI RX0 D-PHY use registers in "general register files", it
+should be a child of the GRF.
+MIPI TXRX D-PHY have its own registers, it must have a reg property.
+
+Optional properties:
+- reg: offset and length of the register set for the device.
+
+port node
+---
+
+The device node should contain two 'port' child nodes, according to the 
bindings
+defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+The first port show the sensors connected in this mipi-dphy.
+- endpoint:
+   - remote-endpoint: Linked to a sensor with a MIPI CSI-2 video bus.
+   - data-lanes : (required) an array specifying active physical MIPI-CSI2
+   data input lanes and their mapping to logical lanes; the
+   D-PHY can't reroute lanes, so the array's content should
+   be consecutive and only its length is meaningful.
+
+The port node must contain at least one endpoint. It could have multiple 
endpoints
+linked to different sensors, but please note that they are not supposed to be
+activated at the same time.
+
+The second port should be connected to isp node.
+- endpoint:
+   - remote-endpoint:  Linked to Rockchip ISP1, which is defined
+   in rockchip-isp1.txt.
+
+Device node example
+---
+
+grf: syscon@ff77 {
+   compatible = "rockchip,rk3288-grf", "syscon", "simple-mfd";
+
+...
+
+   mipi_dphy_rx0: mipi-dphy-rx0 {
+   compatible = "rockchip,rk3399-mipi-dphy";
+   clocks = < SCLK_MIPIDPHY_REF>,
+   < SCLK_DPHY_RX0_CFG>,
+   < PCLK_VIO_GRF>;
+   clock-names = "dphy-ref", "dphy-cfg", "grf";
+   power-domains = < RK3399_PD_VIO>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port@0 {
+   reg = <0>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   mipi_in_wcam: endpoint@0 {
+   reg = <0>;
+   remote-endpoint = <_out>;
+   data-lanes = <1 2>;
+   };
+   mipi_in_ucam: endpoint@1 {
+   reg = <1>;
+   remote-endpoint = <_out>;
+   data-lanes = <1>;
+   };
+   };
+
+   port@1 {
+   reg = <1>;
+
+   dphy_rx0_out: endpoint {
+   remote-endpoint = <_mipi_in>;
+   };
+   };
+   };
+   };
+};
-- 
1.9.1



[PATCH v5 14/16] arm64: dts: rockchip: add isp0 node for rk3399

2017-12-29 Thread Shunqian Zheng
rk3399 have two ISP, but we havn't test isp1, so just add isp0 at present.

Signed-off-by: Shunqian Zheng 
Signed-off-by: Jacob Chen 
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index d340b58a..66a912f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1588,6 +1588,21 @@
status = "disabled";
};
 
+   isp0: isp0@ff91 {
+   compatible = "rockchip,rk3399-cif-isp";
+   reg = <0x0 0xff91 0x0 0x4000>;
+   interrupts = ;
+   clocks = < SCLK_ISP0>,
+< ACLK_ISP0>, < ACLK_ISP0_WRAPPER>,
+< HCLK_ISP0>, < HCLK_ISP0_WRAPPER>;
+   clock-names = "clk_isp",
+ "aclk_isp", "aclk_isp_wrap",
+ "hclk_isp", "hclk_isp_wrap";
+   power-domains = < RK3399_PD_ISP0>;
+   iommus = <_mmu>;
+   status = "disabled";
+   };
+
isp0_mmu: iommu@ff914000 {
compatible = "rockchip,iommu";
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;
-- 
1.9.1



[PATCH v5 16/16] MAINTAINERS: add entry for Rockchip ISP1 driver

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen <jacob2.c...@rock-chips.com>

Add MAINTAINERS entry for the rockchip isp1 driver.
This driver is maintained by rockchip officially and it
will be used for rockchip SoC on all linux-kernel based OS.

Signed-off-by: Jacob Chen <jacob2.c...@rock-chips.com>
---
 MAINTAINERS | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 85773bf..b97bc25 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11668,6 +11668,16 @@ F: drivers/hid/hid-roccat*
 F: include/linux/hid-roccat*
 F: Documentation/ABI/*/sysfs-driver-hid-roccat*
 
+ROCKCHIP ISP V1 DRIVER
+M: Jacob chen <jacob2.c...@rock-chips.com>
+M: Shunqian Zheng <zhen...@rock-chips.com>
+M: Yichong Zhong <z...@rock-chips.com>
+L: linux-me...@vger.kernel.org
+S: Maintained
+F: drivers/media/platform/rockchip/isp1/
+F: Documentation/devicetree/bindings/media/rockchip-isp1.txt
+F: Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt
+
 ROCKCHIP RASTER 2D GRAPHIC ACCELERATION UNIT DRIVER
 M: Jacob chen <jacob2.c...@rock-chips.com>
 L: linux-me...@vger.kernel.org
-- 
1.9.1



[PATCH v5 16/16] MAINTAINERS: add entry for Rockchip ISP1 driver

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen 

Add MAINTAINERS entry for the rockchip isp1 driver.
This driver is maintained by rockchip officially and it
will be used for rockchip SoC on all linux-kernel based OS.

Signed-off-by: Jacob Chen 
---
 MAINTAINERS | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 85773bf..b97bc25 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11668,6 +11668,16 @@ F: drivers/hid/hid-roccat*
 F: include/linux/hid-roccat*
 F: Documentation/ABI/*/sysfs-driver-hid-roccat*
 
+ROCKCHIP ISP V1 DRIVER
+M: Jacob chen 
+M: Shunqian Zheng 
+M: Yichong Zhong 
+L: linux-me...@vger.kernel.org
+S: Maintained
+F: drivers/media/platform/rockchip/isp1/
+F: Documentation/devicetree/bindings/media/rockchip-isp1.txt
+F: Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt
+
 ROCKCHIP RASTER 2D GRAPHIC ACCELERATION UNIT DRIVER
 M: Jacob chen 
 L: linux-me...@vger.kernel.org
-- 
1.9.1



[PATCH v5 13/16] ARM: dts: rockchip: add rx0 mipi-phy for rk3288

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen 

It's a Designware MIPI D-PHY, used by ISP in rk3288.

Signed-off-by: Jacob Chen 
---
 arch/arm/boot/dts/rk3288.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 5dbfafb..a4c9a6e 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -864,6 +864,13 @@
status = "disabled";
};
 
+   mipi_phy_rx0: mipi-phy-rx0 {
+   compatible = "rockchip,rk3288-mipi-dphy";
+   clocks = < SCLK_MIPIDSI_24M>, < PCLK_MIPI_CSI>;
+   clock-names = "dphy-ref", "pclk";
+   status = "disabled";
+   };
+
io_domains: io-domains {
compatible = "rockchip,rk3288-io-voltage-domain";
status = "disabled";
-- 
1.9.1



[PATCH v5 13/16] ARM: dts: rockchip: add rx0 mipi-phy for rk3288

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen 

It's a Designware MIPI D-PHY, used by ISP in rk3288.

Signed-off-by: Jacob Chen 
---
 arch/arm/boot/dts/rk3288.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 5dbfafb..a4c9a6e 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -864,6 +864,13 @@
status = "disabled";
};
 
+   mipi_phy_rx0: mipi-phy-rx0 {
+   compatible = "rockchip,rk3288-mipi-dphy";
+   clocks = < SCLK_MIPIDSI_24M>, < PCLK_MIPI_CSI>;
+   clock-names = "dphy-ref", "pclk";
+   status = "disabled";
+   };
+
io_domains: io-domains {
compatible = "rockchip,rk3288-io-voltage-domain";
status = "disabled";
-- 
1.9.1



[PATCH v5 15/16] arm64: dts: rockchip: add rx0 mipi-phy for rk3399

2017-12-28 Thread Shunqian Zheng
It's a Designware MIPI D-PHY, used for ISP0 in rk3399.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Jacob Chen <jacob2.c...@rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 66a912f..8ef321f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1292,6 +1292,16 @@
status = "disabled";
};
 
+   mipi_dphy_rx0: mipi-dphy-rx0 {
+   compatible = "rockchip,rk3399-mipi-dphy";
+   clocks = < SCLK_MIPIDPHY_REF>,
+   < SCLK_DPHY_RX0_CFG>,
+   < PCLK_VIO_GRF>;
+   clock-names = "dphy-ref", "dphy-cfg", "grf";
+   power-domains = < RK3399_PD_VIO>;
+   status = "disabled";
+   };
+
u2phy0: usb2-phy@e450 {
compatible = "rockchip,rk3399-usb2phy";
reg = <0xe450 0x10>;
-- 
1.9.1



[PATCH v5 15/16] arm64: dts: rockchip: add rx0 mipi-phy for rk3399

2017-12-28 Thread Shunqian Zheng
It's a Designware MIPI D-PHY, used for ISP0 in rk3399.

Signed-off-by: Shunqian Zheng 
Signed-off-by: Jacob Chen 
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 66a912f..8ef321f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1292,6 +1292,16 @@
status = "disabled";
};
 
+   mipi_dphy_rx0: mipi-dphy-rx0 {
+   compatible = "rockchip,rk3399-mipi-dphy";
+   clocks = < SCLK_MIPIDPHY_REF>,
+   < SCLK_DPHY_RX0_CFG>,
+   < PCLK_VIO_GRF>;
+   clock-names = "dphy-ref", "dphy-cfg", "grf";
+   power-domains = < RK3399_PD_VIO>;
+   status = "disabled";
+   };
+
u2phy0: usb2-phy@e450 {
compatible = "rockchip,rk3399-usb2phy";
reg = <0xe450 0x10>;
-- 
1.9.1



[PATCH v5 07/16] media: rkisp1: add ISP1 params driver

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen <jacob2.c...@rock-chips.com>

Add the output video driver that accept params from userspace.

Signed-off-by: Jacob Chen <jacob2.c...@rock-chips.com>
Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Yichong Zhong <z...@rock-chips.com>
Signed-off-by: Jacob Chen <c...@rock-chips.com>
Signed-off-by: Eddie Cai <eddie.cai.li...@gmail.com>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Signed-off-by: Allon Huang <allon.hu...@rock-chips.com>
Signed-off-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/media/platform/rockchip/isp1/isp_params.c | 1553 +
 drivers/media/platform/rockchip/isp1/isp_params.h |   76 +
 2 files changed, 1629 insertions(+)
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.c
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.h

diff --git a/drivers/media/platform/rockchip/isp1/isp_params.c 
b/drivers/media/platform/rockchip/isp1/isp_params.c
new file mode 100644
index 000..7a90965
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/isp_params.c
@@ -0,0 +1,1553 @@
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *  - Redistributions of source code must retain the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer in the documentation and/or other materials
+ *provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include/* for ISP params */
+#include "dev.h"
+#include "regs.h"
+
+#define RKISP1_ISP_PARAMS_REQ_BUFS_MIN 2
+#define RKISP1_ISP_PARAMS_REQ_BUFS_MAX 8
+
+#define BLS_START_H_MAX_IS_VALID(val)  ((val) < CIFISP_BLS_START_H_MAX)
+#define BLS_STOP_H_MAX_IS_VALID(val)   ((val) < CIFISP_BLS_STOP_H_MAX)
+
+#define BLS_START_V_MAX_IS_VALID(val)  ((val) < CIFISP_BLS_START_V_MAX)
+#define BLS_STOP_V_MAX_IS_VALID(val)   ((val) < CIFISP_BLS_STOP_V_MAX)
+
+#define BLS_SAMPLE_MAX_IS_VALID(val)   ((val) < CIFISP_BLS_SAMPLES_MAX)
+
+#define BLS_FIX_SUB_IS_VALID(val)  \
+   ((val) > (s16) CIFISP_BLS_FIX_SUB_MIN && (val) < CIFISP_BLS_FIX_SUB_MAX)
+
+#define RKISP1_ISP_DPCC_LINE_THRESH(n) (CIF_ISP_DPCC_LINE_THRESH_1 + 0x14 * 
(n))
+#define RKISP1_ISP_DPCC_LINE_MAD_FAC(n) (CIF_ISP_DPCC_LINE_MAD_FAC_1 + 0x14 * 
(n))
+#define RKISP1_ISP_DPCC_PG_FAC(n)  (CIF_ISP_DPCC_PG_FAC_1 + 0x14 * (n))
+#define RKISP1_ISP_DPCC_RND_THRESH(n)  (CIF_ISP_DPCC_RND_THRESH_1 + 0x14 * (n))
+#define RKISP1_ISP_DPCC_RG_FAC(n)  (CIF_ISP_DPCC_RG_FAC_1 + 0x14 * (n))
+#define RKISP1_ISP_CC_COEFF(n) (CIF_ISP_CC_COEFF_0 + (n) * 4)
+
+static inline void rkisp1_iowrite32(struct rkisp1_isp_params_vdev *params_vdev,
+   u32 value, u32 addr)
+{
+   iowrite32(value, params_vdev->dev->base_addr + addr);
+}
+
+static inline u32 rkisp1_ioread32(struct rkisp1_isp_params_vdev *params_vdev,
+ u32 addr)
+{
+   return ioread32(params_vdev->dev->base_addr + addr);
+}
+
+static inline void isp_param_set_bits(struct rkisp1_isp_params_vdev
+*params_vdev,
+ u32 reg, u32 bit_mask)
+{
+   u32 val;
+
+   val = rkisp1_ioread32(params_vdev, reg);
+   rkisp1_iowrite32(params_vdev, val | bit_mask, reg);
+}
+
+static inline void isp_param_clear_bits(struct rkisp1_isp_params_vdev
+  *params_vdev,
+   u32 reg, u32 bit_mask)
+{
+   u32 val;
+
+   val = rkisp1_ioread32(params_vdev, reg);
+   rkisp1_iowrite32(params_vdev, val & ~bit_mask, reg);
+}
+
+/* ISP BP interface function */
+static void dpcc_config(st

[PATCH v5 04/16] media: rkisp1: add Rockchip MIPI Synopsys DPHY driver

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen <jacob2.c...@rock-chips.com>

This commit adds a subdev driver for Rockchip MIPI Synopsys DPHY driver

Signed-off-by: Jacob Chen <jacob2.c...@rock-chips.com>
Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Tomasz Figa <tf...@chromium.org>
---
 .../media/platform/rockchip/isp1/mipi_dphy_sy.c| 787 +
 1 file changed, 787 insertions(+)
 create mode 100644 drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c

diff --git a/drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c 
b/drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c
new file mode 100644
index 000..9421183
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c
@@ -0,0 +1,787 @@
+/*
+ * Rockchip MIPI Synopsys DPHY driver
+ *
+ * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *  - Redistributions of source code must retain the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer in the documentation and/or other materials
+ *provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RK3288_GRF_SOC_CON60x025c
+#define RK3288_GRF_SOC_CON80x0264
+#define RK3288_GRF_SOC_CON90x0268
+#define RK3288_GRF_SOC_CON10   0x026c
+#define RK3288_GRF_SOC_CON14   0x027c
+#define RK3288_GRF_SOC_STATUS210x02d4
+#define RK3288_GRF_IO_VSEL 0x0380
+#define RK3288_GRF_SOC_CON15   0x03a4
+
+#define RK3399_GRF_SOC_CON90x6224
+#define RK3399_GRF_SOC_CON21   0x6254
+#define RK3399_GRF_SOC_CON22   0x6258
+#define RK3399_GRF_SOC_CON23   0x625c
+#define RK3399_GRF_SOC_CON24   0x6260
+#define RK3399_GRF_SOC_CON25   0x6264
+#define RK3399_GRF_SOC_STATUS1 0xe2a4
+
+#define CLOCK_LANE_HS_RX_CONTROL   0x34
+#define LANE0_HS_RX_CONTROL0x44
+#define LANE1_HS_RX_CONTROL0x54
+#define LANE2_HS_RX_CONTROL0x84
+#define LANE3_HS_RX_CONTROL0x94
+#define HS_RX_DATA_LANES_THS_SETTLE__CONTROL   0x75
+
+#define HIWORD_UPDATE(val, mask, shift) \
+   ((val) << (shift) | (mask) << ((shift) + 16))
+
+enum mipi_dphy_sy_pads {
+   MIPI_DPHY_SY_PAD_SINK = 0,
+   MIPI_DPHY_SY_PAD_SOURCE,
+   MIPI_DPHY_SY_PADS_NUM,
+};
+
+enum dphy_reg_id {
+   GRF_DPHY_RX0_TURNDISABLE = 0,
+   GRF_DPHY_RX0_FORCERXMODE,
+   GRF_DPHY_RX0_FORCETXSTOPMODE,
+   GRF_DPHY_RX0_ENABLE,
+   GRF_DPHY_RX0_TESTCLR,
+   GRF_DPHY_RX0_TESTCLK,
+   GRF_DPHY_RX0_TESTEN,
+   GRF_DPHY_RX0_TESTDIN,
+   GRF_DPHY_RX0_TURNREQUEST,
+   GRF_DPHY_RX0_TESTDOUT,
+   GRF_DPHY_TX0_TURNDISABLE,
+   GRF_DPHY_TX0_FORCERXMODE,
+   GRF_DPHY_TX0_FORCETXSTOPMODE,
+   GRF_DPHY_TX0_TURNREQUEST,
+   GRF_DPHY_TX1RX1_TURNDISABLE,
+   GRF_DPHY_TX1RX1_FORCERXMODE,
+   GRF_DPHY_TX1RX1_FORCETXSTOPMODE,
+   GRF_DPHY_TX1RX1_ENABLE,
+   GRF_DPHY_TX1RX1_MASTERSLAVEZ,
+   GRF_DPHY_TX1RX1_BASEDIR,
+   GRF_DPHY_TX1RX1_ENABLECLK,
+   GRF_DPHY_TX1RX1_TURNREQUEST,
+   GRF_DPHY_RX1_SRC_SEL,
+   /* rk3288 only */
+   GRF_CON_DISABLE_ISP,
+   GRF_CON_ISP_DPHY_SEL,
+   GRF_DSI_CSI_TESTBUS_SEL,
+   GRF_DVP_V18SEL,
+   /* below is for rk3399 only */
+   GRF_DPHY_RX0_CLK_INV_SEL,
+   GRF_DPHY_RX1_CLK_INV_SEL,
+};
+
+struct dphy_reg {
+   u32 offset;
+   u32 mask;
+   u32 shift;
+};
+
+#define PHY_REG(_offset, _width, _shift) \
+   { .offset = _offset, .mask = BIT(_width) - 1, .shift = _shift, }
+
+static const struct dphy_reg rk3399_grf_dphy_regs[] = {
+   [GRF_DPHY_RX0_TURNREQUEST] = PHY_REG(RK3399_GRF_SOC_CON9, 4, 0),
+   [GRF_DPHY_RX0_CLK

[PATCH v5 00/16] Rockchip ISP1 Driver

2017-12-28 Thread Shunqian Zheng
changes in V5: Sync with local changes,
  - fix the SP height limit
  - speed up the second stream capture
  - the second stream can't force sync for rsz when start/stop streaming
  - add frame id to param vb2 buf
  - enable luminance maximum threshold

changes in V4:
  - fix some bugs during development
  - move quantization settings to rkisp1 subdev
  - correct some spelling problems
  - describe ports in dt-binding documents

changes in V3:
  - add some comments
  - fix wrong use of v4l2_async_subdev_notifier_register
  - optimize two paths capture at a time
  - remove compose
  - re-struct headers
  - add a tmp wiki page: http://opensource.rock-chips.com/wiki_Rockchip-isp1

changes in V2:
  mipi-phy:
- use async probing
- make it be a child device of the GRF
  isp:
- add dummy buffer
- change the way to get bus configuration, which make it possible to
add parallel sensor support in the future(without mipi-phy driver).

This patch series add a ISP(Camera) v4l2 driver for rockchip rk3288/rk3399 SoC.

Wiki Pages:
http://opensource.rock-chips.com/wiki_Rockchip-isp1

Jacob Chen (12):
  media: doc: add document for rkisp1 meta buffer format
  media: rkisp1: add Rockchip MIPI Synopsys DPHY driver
  media: rkisp1: add Rockchip ISP1 subdev driver
  media: rkisp1: add ISP1 statistics driver
  media: rkisp1: add ISP1 params driver
  media: rkisp1: add capture device driver
  media: rkisp1: add rockchip isp1 core driver
  dt-bindings: Document the Rockchip ISP1 bindings
  dt-bindings: Document the Rockchip MIPI RX D-PHY bindings
  ARM: dts: rockchip: add isp node for rk3288
  ARM: dts: rockchip: add rx0 mipi-phy for rk3288
  MAINTAINERS: add entry for Rockchip ISP1 driver

Jeffy Chen (1):
  media: rkisp1: Add user space ABI definitions

Shunqian Zheng (3):
  media: videodev2.h, v4l2-ioctl: add rkisp1 meta buffer format
  arm64: dts: rockchip: add isp0 node for rk3399
  arm64: dts: rockchip: add rx0 mipi-phy for rk3399

 .../devicetree/bindings/media/rockchip-isp1.txt|   69 +
 .../bindings/media/rockchip-mipi-dphy.txt  |   88 +
 Documentation/media/uapi/v4l/meta-formats.rst  |2 +
 .../media/uapi/v4l/pixfmt-meta-rkisp1-params.rst   |   17 +
 .../media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst |   18 +
 MAINTAINERS|   10 +
 arch/arm/boot/dts/rk3288.dtsi  |   24 +
 arch/arm64/boot/dts/rockchip/rk3399.dtsi   |   25 +
 drivers/media/platform/Kconfig |   10 +
 drivers/media/platform/Makefile|1 +
 drivers/media/platform/rockchip/isp1/Makefile  |8 +
 drivers/media/platform/rockchip/isp1/capture.c | 1728 
 drivers/media/platform/rockchip/isp1/capture.h |  194 +++
 drivers/media/platform/rockchip/isp1/common.h  |  137 ++
 drivers/media/platform/rockchip/isp1/dev.c |  653 
 drivers/media/platform/rockchip/isp1/dev.h |  120 ++
 drivers/media/platform/rockchip/isp1/isp_params.c  | 1553 ++
 drivers/media/platform/rockchip/isp1/isp_params.h  |   76 +
 drivers/media/platform/rockchip/isp1/isp_stats.c   |  522 ++
 drivers/media/platform/rockchip/isp1/isp_stats.h   |   85 +
 .../media/platform/rockchip/isp1/mipi_dphy_sy.c|  787 +
 drivers/media/platform/rockchip/isp1/regs.c|  266 +++
 drivers/media/platform/rockchip/isp1/regs.h| 1577 ++
 drivers/media/platform/rockchip/isp1/rkisp1.c  | 1205 ++
 drivers/media/platform/rockchip/isp1/rkisp1.h  |  132 ++
 drivers/media/v4l2-core/v4l2-ioctl.c   |2 +
 include/uapi/linux/rkisp1-config.h |  757 +
 include/uapi/linux/videodev2.h |4 +
 28 files changed, 10070 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/rockchip-isp1.txt
 create mode 100644 
Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt
 create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
 create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
 create mode 100644 drivers/media/platform/rockchip/isp1/Makefile
 create mode 100644 drivers/media/platform/rockchip/isp1/capture.c
 create mode 100644 drivers/media/platform/rockchip/isp1/capture.h
 create mode 100644 drivers/media/platform/rockchip/isp1/common.h
 create mode 100644 drivers/media/platform/rockchip/isp1/dev.c
 create mode 100644 drivers/media/platform/rockchip/isp1/dev.h
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.c
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.h
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.c
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.h
 create mode 100644 drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c
 create mode 100644 drivers/media/platform/rockchip/isp1/regs.c
 create mode 100644 drivers/media/platform/rockchip

[PATCH v5 07/16] media: rkisp1: add ISP1 params driver

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen 

Add the output video driver that accept params from userspace.

Signed-off-by: Jacob Chen 
Signed-off-by: Shunqian Zheng 
Signed-off-by: Yichong Zhong 
Signed-off-by: Jacob Chen 
Signed-off-by: Eddie Cai 
Signed-off-by: Jeffy Chen 
Signed-off-by: Allon Huang 
Signed-off-by: Tomasz Figa 
---
 drivers/media/platform/rockchip/isp1/isp_params.c | 1553 +
 drivers/media/platform/rockchip/isp1/isp_params.h |   76 +
 2 files changed, 1629 insertions(+)
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.c
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.h

diff --git a/drivers/media/platform/rockchip/isp1/isp_params.c 
b/drivers/media/platform/rockchip/isp1/isp_params.c
new file mode 100644
index 000..7a90965
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/isp_params.c
@@ -0,0 +1,1553 @@
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *  - Redistributions of source code must retain the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer in the documentation and/or other materials
+ *provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include/* for ISP params */
+#include "dev.h"
+#include "regs.h"
+
+#define RKISP1_ISP_PARAMS_REQ_BUFS_MIN 2
+#define RKISP1_ISP_PARAMS_REQ_BUFS_MAX 8
+
+#define BLS_START_H_MAX_IS_VALID(val)  ((val) < CIFISP_BLS_START_H_MAX)
+#define BLS_STOP_H_MAX_IS_VALID(val)   ((val) < CIFISP_BLS_STOP_H_MAX)
+
+#define BLS_START_V_MAX_IS_VALID(val)  ((val) < CIFISP_BLS_START_V_MAX)
+#define BLS_STOP_V_MAX_IS_VALID(val)   ((val) < CIFISP_BLS_STOP_V_MAX)
+
+#define BLS_SAMPLE_MAX_IS_VALID(val)   ((val) < CIFISP_BLS_SAMPLES_MAX)
+
+#define BLS_FIX_SUB_IS_VALID(val)  \
+   ((val) > (s16) CIFISP_BLS_FIX_SUB_MIN && (val) < CIFISP_BLS_FIX_SUB_MAX)
+
+#define RKISP1_ISP_DPCC_LINE_THRESH(n) (CIF_ISP_DPCC_LINE_THRESH_1 + 0x14 * 
(n))
+#define RKISP1_ISP_DPCC_LINE_MAD_FAC(n) (CIF_ISP_DPCC_LINE_MAD_FAC_1 + 0x14 * 
(n))
+#define RKISP1_ISP_DPCC_PG_FAC(n)  (CIF_ISP_DPCC_PG_FAC_1 + 0x14 * (n))
+#define RKISP1_ISP_DPCC_RND_THRESH(n)  (CIF_ISP_DPCC_RND_THRESH_1 + 0x14 * (n))
+#define RKISP1_ISP_DPCC_RG_FAC(n)  (CIF_ISP_DPCC_RG_FAC_1 + 0x14 * (n))
+#define RKISP1_ISP_CC_COEFF(n) (CIF_ISP_CC_COEFF_0 + (n) * 4)
+
+static inline void rkisp1_iowrite32(struct rkisp1_isp_params_vdev *params_vdev,
+   u32 value, u32 addr)
+{
+   iowrite32(value, params_vdev->dev->base_addr + addr);
+}
+
+static inline u32 rkisp1_ioread32(struct rkisp1_isp_params_vdev *params_vdev,
+ u32 addr)
+{
+   return ioread32(params_vdev->dev->base_addr + addr);
+}
+
+static inline void isp_param_set_bits(struct rkisp1_isp_params_vdev
+*params_vdev,
+ u32 reg, u32 bit_mask)
+{
+   u32 val;
+
+   val = rkisp1_ioread32(params_vdev, reg);
+   rkisp1_iowrite32(params_vdev, val | bit_mask, reg);
+}
+
+static inline void isp_param_clear_bits(struct rkisp1_isp_params_vdev
+  *params_vdev,
+   u32 reg, u32 bit_mask)
+{
+   u32 val;
+
+   val = rkisp1_ioread32(params_vdev, reg);
+   rkisp1_iowrite32(params_vdev, val & ~bit_mask, reg);
+}
+
+/* ISP BP interface function */
+static void dpcc_config(struct rkisp1_isp_params_vdev *params_vdev,
+   const struct cifisp_dpcc_config *arg)
+{
+   unsigned int i;
+
+   rkisp1_iowrite32(params_vdev, arg->mode, CIF_ISP_DPCC_MODE);
+   rkisp1_iowrite32(params_vdev, arg->output_mode,
+   

[PATCH v5 04/16] media: rkisp1: add Rockchip MIPI Synopsys DPHY driver

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen 

This commit adds a subdev driver for Rockchip MIPI Synopsys DPHY driver

Signed-off-by: Jacob Chen 
Signed-off-by: Shunqian Zheng 
Signed-off-by: Tomasz Figa 
---
 .../media/platform/rockchip/isp1/mipi_dphy_sy.c| 787 +
 1 file changed, 787 insertions(+)
 create mode 100644 drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c

diff --git a/drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c 
b/drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c
new file mode 100644
index 000..9421183
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c
@@ -0,0 +1,787 @@
+/*
+ * Rockchip MIPI Synopsys DPHY driver
+ *
+ * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *  - Redistributions of source code must retain the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer in the documentation and/or other materials
+ *provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RK3288_GRF_SOC_CON60x025c
+#define RK3288_GRF_SOC_CON80x0264
+#define RK3288_GRF_SOC_CON90x0268
+#define RK3288_GRF_SOC_CON10   0x026c
+#define RK3288_GRF_SOC_CON14   0x027c
+#define RK3288_GRF_SOC_STATUS210x02d4
+#define RK3288_GRF_IO_VSEL 0x0380
+#define RK3288_GRF_SOC_CON15   0x03a4
+
+#define RK3399_GRF_SOC_CON90x6224
+#define RK3399_GRF_SOC_CON21   0x6254
+#define RK3399_GRF_SOC_CON22   0x6258
+#define RK3399_GRF_SOC_CON23   0x625c
+#define RK3399_GRF_SOC_CON24   0x6260
+#define RK3399_GRF_SOC_CON25   0x6264
+#define RK3399_GRF_SOC_STATUS1 0xe2a4
+
+#define CLOCK_LANE_HS_RX_CONTROL   0x34
+#define LANE0_HS_RX_CONTROL0x44
+#define LANE1_HS_RX_CONTROL0x54
+#define LANE2_HS_RX_CONTROL0x84
+#define LANE3_HS_RX_CONTROL0x94
+#define HS_RX_DATA_LANES_THS_SETTLE__CONTROL   0x75
+
+#define HIWORD_UPDATE(val, mask, shift) \
+   ((val) << (shift) | (mask) << ((shift) + 16))
+
+enum mipi_dphy_sy_pads {
+   MIPI_DPHY_SY_PAD_SINK = 0,
+   MIPI_DPHY_SY_PAD_SOURCE,
+   MIPI_DPHY_SY_PADS_NUM,
+};
+
+enum dphy_reg_id {
+   GRF_DPHY_RX0_TURNDISABLE = 0,
+   GRF_DPHY_RX0_FORCERXMODE,
+   GRF_DPHY_RX0_FORCETXSTOPMODE,
+   GRF_DPHY_RX0_ENABLE,
+   GRF_DPHY_RX0_TESTCLR,
+   GRF_DPHY_RX0_TESTCLK,
+   GRF_DPHY_RX0_TESTEN,
+   GRF_DPHY_RX0_TESTDIN,
+   GRF_DPHY_RX0_TURNREQUEST,
+   GRF_DPHY_RX0_TESTDOUT,
+   GRF_DPHY_TX0_TURNDISABLE,
+   GRF_DPHY_TX0_FORCERXMODE,
+   GRF_DPHY_TX0_FORCETXSTOPMODE,
+   GRF_DPHY_TX0_TURNREQUEST,
+   GRF_DPHY_TX1RX1_TURNDISABLE,
+   GRF_DPHY_TX1RX1_FORCERXMODE,
+   GRF_DPHY_TX1RX1_FORCETXSTOPMODE,
+   GRF_DPHY_TX1RX1_ENABLE,
+   GRF_DPHY_TX1RX1_MASTERSLAVEZ,
+   GRF_DPHY_TX1RX1_BASEDIR,
+   GRF_DPHY_TX1RX1_ENABLECLK,
+   GRF_DPHY_TX1RX1_TURNREQUEST,
+   GRF_DPHY_RX1_SRC_SEL,
+   /* rk3288 only */
+   GRF_CON_DISABLE_ISP,
+   GRF_CON_ISP_DPHY_SEL,
+   GRF_DSI_CSI_TESTBUS_SEL,
+   GRF_DVP_V18SEL,
+   /* below is for rk3399 only */
+   GRF_DPHY_RX0_CLK_INV_SEL,
+   GRF_DPHY_RX1_CLK_INV_SEL,
+};
+
+struct dphy_reg {
+   u32 offset;
+   u32 mask;
+   u32 shift;
+};
+
+#define PHY_REG(_offset, _width, _shift) \
+   { .offset = _offset, .mask = BIT(_width) - 1, .shift = _shift, }
+
+static const struct dphy_reg rk3399_grf_dphy_regs[] = {
+   [GRF_DPHY_RX0_TURNREQUEST] = PHY_REG(RK3399_GRF_SOC_CON9, 4, 0),
+   [GRF_DPHY_RX0_CLK_INV_SEL] = PHY_REG(RK3399_GRF_SOC_CON9, 1, 10),
+   [GRF_DPHY_RX1_CLK_INV_SEL] = PHY_REG(RK3399_GRF_SOC_CON9, 1, 11),
+   [GRF_DPHY

[PATCH v5 00/16] Rockchip ISP1 Driver

2017-12-28 Thread Shunqian Zheng
changes in V5: Sync with local changes,
  - fix the SP height limit
  - speed up the second stream capture
  - the second stream can't force sync for rsz when start/stop streaming
  - add frame id to param vb2 buf
  - enable luminance maximum threshold

changes in V4:
  - fix some bugs during development
  - move quantization settings to rkisp1 subdev
  - correct some spelling problems
  - describe ports in dt-binding documents

changes in V3:
  - add some comments
  - fix wrong use of v4l2_async_subdev_notifier_register
  - optimize two paths capture at a time
  - remove compose
  - re-struct headers
  - add a tmp wiki page: http://opensource.rock-chips.com/wiki_Rockchip-isp1

changes in V2:
  mipi-phy:
- use async probing
- make it be a child device of the GRF
  isp:
- add dummy buffer
- change the way to get bus configuration, which make it possible to
add parallel sensor support in the future(without mipi-phy driver).

This patch series add a ISP(Camera) v4l2 driver for rockchip rk3288/rk3399 SoC.

Wiki Pages:
http://opensource.rock-chips.com/wiki_Rockchip-isp1

Jacob Chen (12):
  media: doc: add document for rkisp1 meta buffer format
  media: rkisp1: add Rockchip MIPI Synopsys DPHY driver
  media: rkisp1: add Rockchip ISP1 subdev driver
  media: rkisp1: add ISP1 statistics driver
  media: rkisp1: add ISP1 params driver
  media: rkisp1: add capture device driver
  media: rkisp1: add rockchip isp1 core driver
  dt-bindings: Document the Rockchip ISP1 bindings
  dt-bindings: Document the Rockchip MIPI RX D-PHY bindings
  ARM: dts: rockchip: add isp node for rk3288
  ARM: dts: rockchip: add rx0 mipi-phy for rk3288
  MAINTAINERS: add entry for Rockchip ISP1 driver

Jeffy Chen (1):
  media: rkisp1: Add user space ABI definitions

Shunqian Zheng (3):
  media: videodev2.h, v4l2-ioctl: add rkisp1 meta buffer format
  arm64: dts: rockchip: add isp0 node for rk3399
  arm64: dts: rockchip: add rx0 mipi-phy for rk3399

 .../devicetree/bindings/media/rockchip-isp1.txt|   69 +
 .../bindings/media/rockchip-mipi-dphy.txt  |   88 +
 Documentation/media/uapi/v4l/meta-formats.rst  |2 +
 .../media/uapi/v4l/pixfmt-meta-rkisp1-params.rst   |   17 +
 .../media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst |   18 +
 MAINTAINERS|   10 +
 arch/arm/boot/dts/rk3288.dtsi  |   24 +
 arch/arm64/boot/dts/rockchip/rk3399.dtsi   |   25 +
 drivers/media/platform/Kconfig |   10 +
 drivers/media/platform/Makefile|1 +
 drivers/media/platform/rockchip/isp1/Makefile  |8 +
 drivers/media/platform/rockchip/isp1/capture.c | 1728 
 drivers/media/platform/rockchip/isp1/capture.h |  194 +++
 drivers/media/platform/rockchip/isp1/common.h  |  137 ++
 drivers/media/platform/rockchip/isp1/dev.c |  653 
 drivers/media/platform/rockchip/isp1/dev.h |  120 ++
 drivers/media/platform/rockchip/isp1/isp_params.c  | 1553 ++
 drivers/media/platform/rockchip/isp1/isp_params.h  |   76 +
 drivers/media/platform/rockchip/isp1/isp_stats.c   |  522 ++
 drivers/media/platform/rockchip/isp1/isp_stats.h   |   85 +
 .../media/platform/rockchip/isp1/mipi_dphy_sy.c|  787 +
 drivers/media/platform/rockchip/isp1/regs.c|  266 +++
 drivers/media/platform/rockchip/isp1/regs.h| 1577 ++
 drivers/media/platform/rockchip/isp1/rkisp1.c  | 1205 ++
 drivers/media/platform/rockchip/isp1/rkisp1.h  |  132 ++
 drivers/media/v4l2-core/v4l2-ioctl.c   |2 +
 include/uapi/linux/rkisp1-config.h |  757 +
 include/uapi/linux/videodev2.h |4 +
 28 files changed, 10070 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/rockchip-isp1.txt
 create mode 100644 
Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt
 create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
 create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
 create mode 100644 drivers/media/platform/rockchip/isp1/Makefile
 create mode 100644 drivers/media/platform/rockchip/isp1/capture.c
 create mode 100644 drivers/media/platform/rockchip/isp1/capture.h
 create mode 100644 drivers/media/platform/rockchip/isp1/common.h
 create mode 100644 drivers/media/platform/rockchip/isp1/dev.c
 create mode 100644 drivers/media/platform/rockchip/isp1/dev.h
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.c
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.h
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.c
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.h
 create mode 100644 drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c
 create mode 100644 drivers/media/platform/rockchip/isp1/regs.c
 create mode 100644 drivers/media/platform/rockchip

[PATCH v5 06/16] media: rkisp1: add ISP1 statistics driver

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen <jacob2.c...@rock-chips.com>

Add the capture video driver for rockchip isp1 statistics block.

Signed-off-by: Jacob Chen <jacob2.c...@rock-chips.com>
Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Yichong Zhong <z...@rock-chips.com>
Signed-off-by: Jacob Chen <c...@rock-chips.com>
Signed-off-by: Eddie Cai <eddie.cai.li...@gmail.com>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Signed-off-by: Allon Huang <allon.hu...@rock-chips.com>
Signed-off-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/media/platform/rockchip/isp1/isp_stats.c | 522 +++
 drivers/media/platform/rockchip/isp1/isp_stats.h |  85 
 2 files changed, 607 insertions(+)
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.c
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.h

diff --git a/drivers/media/platform/rockchip/isp1/isp_stats.c 
b/drivers/media/platform/rockchip/isp1/isp_stats.c
new file mode 100644
index 000..dd30ebe
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/isp_stats.c
@@ -0,0 +1,522 @@
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *  - Redistributions of source code must retain the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer in the documentation and/or other materials
+ *provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include/* for ISP statistics */
+#include "dev.h"
+#include "regs.h"
+
+#define RKISP1_ISP_STATS_REQ_BUFS_MIN 2
+#define RKISP1_ISP_STATS_REQ_BUFS_MAX 8
+
+static int rkisp1_stats_enum_fmt_meta_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+   struct video_device *video = video_devdata(file);
+   struct rkisp1_isp_stats_vdev *stats_vdev = video_get_drvdata(video);
+
+   if (f->index > 0 || f->type != video->queue->type)
+   return -EINVAL;
+
+   f->pixelformat = stats_vdev->vdev_fmt.fmt.meta.dataformat;
+   return 0;
+}
+
+static int rkisp1_stats_g_fmt_meta_cap(struct file *file, void *priv,
+  struct v4l2_format *f)
+{
+   struct video_device *video = video_devdata(file);
+   struct rkisp1_isp_stats_vdev *stats_vdev = video_get_drvdata(video);
+   struct v4l2_meta_format *meta = >fmt.meta;
+
+   if (f->type != video->queue->type)
+   return -EINVAL;
+
+   memset(meta, 0, sizeof(*meta));
+   meta->dataformat = stats_vdev->vdev_fmt.fmt.meta.dataformat;
+   meta->buffersize = stats_vdev->vdev_fmt.fmt.meta.buffersize;
+
+   return 0;
+}
+
+static int rkisp1_stats_querycap(struct file *file,
+void *priv, struct v4l2_capability *cap)
+{
+   struct video_device *vdev = video_devdata(file);
+
+   strcpy(cap->driver, DRIVER_NAME);
+   strlcpy(cap->card, vdev->name, sizeof(cap->card));
+   strlcpy(cap->bus_info, "platform: " DRIVER_NAME, sizeof(cap->bus_info));
+
+   return 0;
+}
+
+/* ISP video device IOCTLs */
+static const struct v4l2_ioctl_ops rkisp1_stats_ioctl = {
+   .vidioc_reqbufs = vb2_ioctl_reqbufs,
+   .vidioc_querybuf = vb2_ioctl_querybuf,
+   .vidioc_create_bufs = vb2_ioctl_create_bufs,
+   .vidioc_qbuf = vb2_ioctl_qbuf,
+   .vidioc_dqbuf = vb2_ioctl_dqbuf,
+   .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+   .vidioc_expbuf = vb2_ioctl_expbuf,
+   .vidioc_streamon = vb2_ioctl_streamon,
+   .vidioc_streamoff = vb2_ioctl_streamoff,
+   .vidioc_enum_fmt_meta_cap = rkisp1_stats_enum_fmt_meta_cap,
+   .vidioc_g_fmt_meta_ca

[PATCH v5 08/16] media: rkisp1: add capture device driver

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen <jacob2.c...@rock-chips.com>

This is the capture device interface driver that provides the v4l2
user interface. Frames can be received from ISP1.

Signed-off-by: Jacob Chen <jacob2.c...@rock-chips.com>
Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Yichong Zhong <z...@rock-chips.com>
Signed-off-by: Jacob Chen <c...@rock-chips.com>
Signed-off-by: Eddie Cai <eddie.cai.li...@gmail.com>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Signed-off-by: Allon Huang <allon.hu...@rock-chips.com>
Signed-off-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/media/platform/rockchip/isp1/capture.c | 1728 
 drivers/media/platform/rockchip/isp1/capture.h |  194 +++
 drivers/media/platform/rockchip/isp1/regs.c|  266 
 drivers/media/platform/rockchip/isp1/regs.h| 1577 +
 4 files changed, 3765 insertions(+)
 create mode 100644 drivers/media/platform/rockchip/isp1/capture.c
 create mode 100644 drivers/media/platform/rockchip/isp1/capture.h
 create mode 100644 drivers/media/platform/rockchip/isp1/regs.c
 create mode 100644 drivers/media/platform/rockchip/isp1/regs.h

diff --git a/drivers/media/platform/rockchip/isp1/capture.c 
b/drivers/media/platform/rockchip/isp1/capture.c
new file mode 100644
index 000..a232dce
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/capture.c
@@ -0,0 +1,1729 @@
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *  - Redistributions of source code must retain the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer in the documentation and/or other materials
+ *provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "dev.h"
+#include "regs.h"
+
+/*
+ * NOTE:
+ * 1. There are two capture video devices in rkisp1, selfpath and mainpath
+ * 2. Two capture device have separated memory-interface/crop/scale units.
+ * 3. Besides describing stream hardware, this file also contain entries
+ *for pipeline operations.
+ * 4. The register read/write operations in this file are put into regs.c.
+ */
+
+/*
+ * differences between selfpatch and mainpath
+ * available mp sink input: isp
+ * available sp sink input : isp, dma(TODO)
+ * available mp sink pad fmts: yuv422, raw
+ * available sp sink pad fmts: yuv422, yuv420..
+ * available mp source fmts: yuv, raw, jpeg(TODO)
+ * available sp source fmts: yuv, rgb
+ */
+
+#define CIF_ISP_REQ_BUFS_MIN 1
+#define CIF_ISP_REQ_BUFS_MAX 8
+
+#define STREAM_PAD_SINK0
+#define STREAM_PAD_SOURCE  1
+
+#define STREAM_MAX_MP_RSZ_OUTPUT_WIDTH 4416
+#define STREAM_MAX_MP_RSZ_OUTPUT_HEIGHT3312
+#define STREAM_MAX_SP_RSZ_OUTPUT_WIDTH 1920
+#define STREAM_MAX_SP_RSZ_OUTPUT_HEIGHT1920
+#define STREAM_MIN_RSZ_OUTPUT_WIDTH32
+#define STREAM_MIN_RSZ_OUTPUT_HEIGHT   16
+
+#define STREAM_MAX_MP_SP_INPUT_WIDTH STREAM_MAX_MP_RSZ_OUTPUT_WIDTH
+#define STREAM_MAX_MP_SP_INPUT_HEIGHT STREAM_MAX_MP_RSZ_OUTPUT_HEIGHT
+#define STREAM_MIN_MP_SP_INPUT_WIDTH   32
+#define STREAM_MIN_MP_SP_INPUT_HEIGHT  32
+
+/* Get xsubs and ysubs for fourcc formats
+ *
+ * @xsubs: horizontal color samples in a 4*4 matrix, for yuv
+ * @ysubs: vertical color samples in a 4*4 matrix, for yuv
+ */
+static int fcc_xysubs(u32 fcc, u32 *xsubs, u32 *ysubs)
+{
+   switch (fcc) {
+   case V4L2_PIX_FMT_GREY:
+   case V4L2_PIX_FMT_YUV444M:
+   *xsubs = 1;
+   *ysubs = 1;
+   break;
+   case V4L2_PIX_FMT_YUYV:
+   case V4L2_PIX_FMT_Y

[PATCH v5 02/16] media: doc: add document for rkisp1 meta buffer format

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen 

This commit add docuemnt for rkisp1 meta buffer format

Signed-off-by: Jacob Chen 
---
 Documentation/media/uapi/v4l/meta-formats.rst  |  2 ++
 .../media/uapi/v4l/pixfmt-meta-rkisp1-params.rst   | 17 +
 .../media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst | 18 ++
 3 files changed, 37 insertions(+)
 create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
 create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst

diff --git a/Documentation/media/uapi/v4l/meta-formats.rst 
b/Documentation/media/uapi/v4l/meta-formats.rst
index 01e24e3..1b82814 100644
--- a/Documentation/media/uapi/v4l/meta-formats.rst
+++ b/Documentation/media/uapi/v4l/meta-formats.rst
@@ -14,3 +14,5 @@ These formats are used for the :ref:`metadata` interface only.
 
 pixfmt-meta-vsp1-hgo
 pixfmt-meta-vsp1-hgt
+pixfmt-meta-rkisp1-params
+pixfmt-meta-rkisp1-stat
diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst 
b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
new file mode 100644
index 000..ed344d4
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
@@ -0,0 +1,17 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-meta-fmt-rkisp1-params:
+
+***
+V4L2_META_FMT_RK_ISP1_PARAMS
+***
+
+Rockchip ISP1 Parameters Data
+
+Description
+===
+
+This format describes input parameters for the Rockchip ISP1.
+
+The data use c-struct :c:type:`rkisp1_isp_params_cfg`, which is defined in
+the ``linux/rkisp1-config.h`` header file, See it for details.
diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst 
b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
new file mode 100644
index 000..5ecc403
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
@@ -0,0 +1,18 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-meta-fmt-rkisp1-stat:
+
+***
+V4L2_META_FMT_RK_ISP1_STAT_3A
+***
+
+Rockchip ISP1 Statistics Data
+
+Description
+===
+
+This format describes image color statistics information generated by the 
Rockchip
+ISP1.
+
+The data use c-struct :c:type:`rkisp1_stat_buffer`, which is defined in
+the ``linux/cifisp_stat.h`` header file, See it for details.
-- 
1.9.1



[PATCH v5 12/16] ARM: dts: rockchip: add isp node for rk3288

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen 

rk3288 have a Embedded 13M ISP

Signed-off-by: Jacob Chen 
---
 arch/arm/boot/dts/rk3288.dtsi | 17 +
 1 file changed, 17 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index cd24894..5dbfafb 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -962,6 +962,23 @@
status = "disabled";
};
 
+   isp: isp@ff91 {
+   compatible = "rockchip,rk3288-cif-isp";
+   reg = <0x0 0xff91 0x0 0x4000>;
+   interrupts = ;
+   clocks = < SCLK_ISP>, < ACLK_ISP>,
+< HCLK_ISP>, < PCLK_ISP_IN>,
+< SCLK_ISP_JPE>;
+   clock-names = "clk_isp", "aclk_isp",
+ "hclk_isp", "pclk_isp_in",
+ "sclk_isp_jpe";
+   assigned-clocks = < SCLK_ISP>, < SCLK_ISP_JPE>;
+   assigned-clock-rates = <4>, <4>;
+   power-domains = < RK3288_PD_VIO>;
+   iommus = <_mmu>;
+   status = "disabled";
+   };
+
isp_mmu: iommu@ff914000 {
compatible = "rockchip,iommu";
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;
-- 
1.9.1



[PATCH v5 03/16] media: rkisp1: Add user space ABI definitions

2017-12-28 Thread Shunqian Zheng
From: Jeffy Chen 

Add the header for userspace

Signed-off-by: Jeffy Chen 
Signed-off-by: Jacob Chen 
---
 include/uapi/linux/rkisp1-config.h | 757 +
 1 file changed, 757 insertions(+)
 create mode 100644 include/uapi/linux/rkisp1-config.h

diff --git a/include/uapi/linux/rkisp1-config.h 
b/include/uapi/linux/rkisp1-config.h
new file mode 100644
index 000..0f9f4226
--- /dev/null
+++ b/include/uapi/linux/rkisp1-config.h
@@ -0,0 +1,757 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Rockchip isp1 driver
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef _UAPI_RKISP1_CONFIG_H
+#define _UAPI_RKISP1_CONFIG_H
+
+#include 
+#include 
+
+#define CIFISP_MODULE_DPCC  (1 << 0)
+#define CIFISP_MODULE_BLS   (1 << 1)
+#define CIFISP_MODULE_SDG   (1 << 2)
+#define CIFISP_MODULE_HST   (1 << 3)
+#define CIFISP_MODULE_LSC   (1 << 4)
+#define CIFISP_MODULE_AWB_GAIN  (1 << 5)
+#define CIFISP_MODULE_FLT   (1 << 6)
+#define CIFISP_MODULE_BDM   (1 << 7)
+#define CIFISP_MODULE_CTK   (1 << 8)
+#define CIFISP_MODULE_GOC   (1 << 9)
+#define CIFISP_MODULE_CPROC (1 << 10)
+#define CIFISP_MODULE_AFC   (1 << 11)
+#define CIFISP_MODULE_AWB   (1 << 12)
+#define CIFISP_MODULE_IE(1 << 13)
+#define CIFISP_MODULE_AEC   (1 << 14)
+#define CIFISP_MODULE_WDR   (1 << 15)
+#define CIFISP_MODULE_DPF   (1 << 16)
+#define CIFISP_MODULE_DPF_STRENGTH  (1 << 17)
+
+#define CIFISP_CTK_COEFF_MAX0x100
+#define CIFISP_CTK_OFFSET_MAX   0x800
+
+#define CIFISP_AE_MEAN_MAX  25
+#define CIFISP_HIST_BIN_N_MAX   16
+#define CIFISP_AFM_MAX_WINDOWS  3
+#define CIFISP_DEGAMMA_CURVE_SIZE   17
+
+#define CIFISP_BDM_MAX_TH   0xFF
+
+/*
+ * Black level compensation
+ */
+/* maximum value for horizontal start address */
+#define CIFISP_BLS_START_H_MAX 0x0FFF
+/* maximum value for horizontal stop address */
+#define CIFISP_BLS_STOP_H_MAX  0x0FFF
+/* maximum value for vertical start address */
+#define CIFISP_BLS_START_V_MAX 0x0FFF
+/* maximum value for vertical stop address */
+#define CIFISP_BLS_STOP_V_MAX  0x0FFF
+/* maximum is 2^18 = 262144*/
+#define CIFISP_BLS_SAMPLES_MAX 0x0012
+/* maximum value for fixed black level */
+#define CIFISP_BLS_FIX_SUB_MAX 0x0FFF
+/* minimum value for fixed black level */
+#define CIFISP_BLS_FIX_SUB_MIN 0xF000
+/* 13 bit range (signed)*/
+#define CIFISP_BLS_FIX_MASK0x1FFF
+
+/*
+ * Automatic white balance measurments
+ */
+#define CIFISP_AWB_MAX_GRID1
+#define CIFISP_AWB_MAX_FRAMES  7
+
+/*
+ * Gamma out
+ */
+/* Maximum number of color samples supported */
+#define CIFISP_GAMMA_OUT_MAX_SAMPLES   17
+
+/*
+ * Lens shade correction
+ */
+#define CIFISP_LSC_GRAD_TBL_SIZE   8
+#define CIFISP_LSC_SIZE_TBL_SIZE   8
+/*
+ * The following matches the tuning process,
+ * not the max capabilities of the chip.
+ * Last value unused.
+ */
+#defineCIFISP_LSC_DATA_TBL_SIZE   290
+
+/*
+ * Histogram calculation
+ */
+/* Last 3 values unused. */
+#define CIFISP_HISTOGRAM_WEIGHT_GRIDS_SIZE 28
+
+/*
+ * Defect Pixel Cluster Correction
+ */
+#define CIFISP_DPCC_METHODS_MAX   3
+
+/*
+ * Denoising pre filter
+ */
+#define CIFISP_DPF_MAX_NLF_COEFFS  17
+#define CIFISP_DPF_MAX_SPATIAL_COEFFS  6
+
+/*
+ * Measurement types
+ */
+#define CIFISP_STAT_AWB   (1 << 0)
+#define CIFISP_STAT_AUTOEXP   (1 << 1)
+#define CIFISP_STAT_AFM_FIN   (1 << 2)
+#define CIFISP_STAT_HIST  (1 << 3)
+
+enum cifisp_histogram_mode {
+   CIFISP_HISTOGRAM_MODE_DISABLE,
+   CIFISP_HISTOGRAM_MODE_RGB_COMBINED,
+   CIFISP_HISTOGRAM_MODE_R_HISTOGRAM,
+   CIFISP_HISTOGRAM_MODE_G_HISTOGRAM,
+   CIFISP_HISTOGRAM_MODE_B_HISTOGRAM,
+   CIFISP_HISTOGRAM_MODE_Y_HISTOGRAM
+};
+
+enum cifisp_awb_mode_type {
+   CIFISP_AWB_MODE_MANUAL,
+   CIFISP_AWB_MODE_RGB,
+   CIFISP_AWB_MODE_YCBCR
+};
+
+enum cifisp_flt_mode {
+   CIFISP_FLT_STATIC_MODE,
+   CIFISP_FLT_DYNAMIC_MODE
+};
+
+/**
+ * enum cifisp_exp_ctrl_auotostop - stop modes
+ * @CIFISP_EXP_CTRL_AUTOSTOP_0: continous measurement
+ * @CIFISP_EXP_CTRL_AUTOSTOP_1: stop measuring after a complete frame
+ */
+enum cifisp_exp_ctrl_auotostop {
+   CIFISP_EXP_CTRL_AUTOSTOP_0 = 0,
+   CIFISP_EXP_CTRL_AUTOSTOP_1 = 1,
+};
+
+/**
+ * enum cifisp_exp_meas_mode - Exposure measure mode
+ * @CIFISP_EXP_MEASURING_MODE_0: Y = 16 + 0.25R + 0.5G + 0.1094B
+ * @CIFISP_EXP_MEASURING_MODE_1: Y = (R + G + B) x (85/256)
+ */
+enum cifisp_exp_meas_mode {
+   

[PATCH v5 06/16] media: rkisp1: add ISP1 statistics driver

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen 

Add the capture video driver for rockchip isp1 statistics block.

Signed-off-by: Jacob Chen 
Signed-off-by: Shunqian Zheng 
Signed-off-by: Yichong Zhong 
Signed-off-by: Jacob Chen 
Signed-off-by: Eddie Cai 
Signed-off-by: Jeffy Chen 
Signed-off-by: Allon Huang 
Signed-off-by: Tomasz Figa 
---
 drivers/media/platform/rockchip/isp1/isp_stats.c | 522 +++
 drivers/media/platform/rockchip/isp1/isp_stats.h |  85 
 2 files changed, 607 insertions(+)
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.c
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.h

diff --git a/drivers/media/platform/rockchip/isp1/isp_stats.c 
b/drivers/media/platform/rockchip/isp1/isp_stats.c
new file mode 100644
index 000..dd30ebe
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/isp_stats.c
@@ -0,0 +1,522 @@
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *  - Redistributions of source code must retain the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer in the documentation and/or other materials
+ *provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include/* for ISP statistics */
+#include "dev.h"
+#include "regs.h"
+
+#define RKISP1_ISP_STATS_REQ_BUFS_MIN 2
+#define RKISP1_ISP_STATS_REQ_BUFS_MAX 8
+
+static int rkisp1_stats_enum_fmt_meta_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+   struct video_device *video = video_devdata(file);
+   struct rkisp1_isp_stats_vdev *stats_vdev = video_get_drvdata(video);
+
+   if (f->index > 0 || f->type != video->queue->type)
+   return -EINVAL;
+
+   f->pixelformat = stats_vdev->vdev_fmt.fmt.meta.dataformat;
+   return 0;
+}
+
+static int rkisp1_stats_g_fmt_meta_cap(struct file *file, void *priv,
+  struct v4l2_format *f)
+{
+   struct video_device *video = video_devdata(file);
+   struct rkisp1_isp_stats_vdev *stats_vdev = video_get_drvdata(video);
+   struct v4l2_meta_format *meta = >fmt.meta;
+
+   if (f->type != video->queue->type)
+   return -EINVAL;
+
+   memset(meta, 0, sizeof(*meta));
+   meta->dataformat = stats_vdev->vdev_fmt.fmt.meta.dataformat;
+   meta->buffersize = stats_vdev->vdev_fmt.fmt.meta.buffersize;
+
+   return 0;
+}
+
+static int rkisp1_stats_querycap(struct file *file,
+void *priv, struct v4l2_capability *cap)
+{
+   struct video_device *vdev = video_devdata(file);
+
+   strcpy(cap->driver, DRIVER_NAME);
+   strlcpy(cap->card, vdev->name, sizeof(cap->card));
+   strlcpy(cap->bus_info, "platform: " DRIVER_NAME, sizeof(cap->bus_info));
+
+   return 0;
+}
+
+/* ISP video device IOCTLs */
+static const struct v4l2_ioctl_ops rkisp1_stats_ioctl = {
+   .vidioc_reqbufs = vb2_ioctl_reqbufs,
+   .vidioc_querybuf = vb2_ioctl_querybuf,
+   .vidioc_create_bufs = vb2_ioctl_create_bufs,
+   .vidioc_qbuf = vb2_ioctl_qbuf,
+   .vidioc_dqbuf = vb2_ioctl_dqbuf,
+   .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+   .vidioc_expbuf = vb2_ioctl_expbuf,
+   .vidioc_streamon = vb2_ioctl_streamon,
+   .vidioc_streamoff = vb2_ioctl_streamoff,
+   .vidioc_enum_fmt_meta_cap = rkisp1_stats_enum_fmt_meta_cap,
+   .vidioc_g_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap,
+   .vidioc_s_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap,
+   .vidioc_try_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap,
+   .vidioc_querycap = rkisp1_stats_querycap
+};
+
+struct v4l2_file_operations rkisp1_stats_fops = {
+   .m

[PATCH v5 08/16] media: rkisp1: add capture device driver

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen 

This is the capture device interface driver that provides the v4l2
user interface. Frames can be received from ISP1.

Signed-off-by: Jacob Chen 
Signed-off-by: Shunqian Zheng 
Signed-off-by: Yichong Zhong 
Signed-off-by: Jacob Chen 
Signed-off-by: Eddie Cai 
Signed-off-by: Jeffy Chen 
Signed-off-by: Allon Huang 
Signed-off-by: Tomasz Figa 
---
 drivers/media/platform/rockchip/isp1/capture.c | 1728 
 drivers/media/platform/rockchip/isp1/capture.h |  194 +++
 drivers/media/platform/rockchip/isp1/regs.c|  266 
 drivers/media/platform/rockchip/isp1/regs.h| 1577 +
 4 files changed, 3765 insertions(+)
 create mode 100644 drivers/media/platform/rockchip/isp1/capture.c
 create mode 100644 drivers/media/platform/rockchip/isp1/capture.h
 create mode 100644 drivers/media/platform/rockchip/isp1/regs.c
 create mode 100644 drivers/media/platform/rockchip/isp1/regs.h

diff --git a/drivers/media/platform/rockchip/isp1/capture.c 
b/drivers/media/platform/rockchip/isp1/capture.c
new file mode 100644
index 000..a232dce
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/capture.c
@@ -0,0 +1,1729 @@
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *  - Redistributions of source code must retain the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above
+ *copyright notice, this list of conditions and the following
+ *disclaimer in the documentation and/or other materials
+ *provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "dev.h"
+#include "regs.h"
+
+/*
+ * NOTE:
+ * 1. There are two capture video devices in rkisp1, selfpath and mainpath
+ * 2. Two capture device have separated memory-interface/crop/scale units.
+ * 3. Besides describing stream hardware, this file also contain entries
+ *for pipeline operations.
+ * 4. The register read/write operations in this file are put into regs.c.
+ */
+
+/*
+ * differences between selfpatch and mainpath
+ * available mp sink input: isp
+ * available sp sink input : isp, dma(TODO)
+ * available mp sink pad fmts: yuv422, raw
+ * available sp sink pad fmts: yuv422, yuv420..
+ * available mp source fmts: yuv, raw, jpeg(TODO)
+ * available sp source fmts: yuv, rgb
+ */
+
+#define CIF_ISP_REQ_BUFS_MIN 1
+#define CIF_ISP_REQ_BUFS_MAX 8
+
+#define STREAM_PAD_SINK0
+#define STREAM_PAD_SOURCE  1
+
+#define STREAM_MAX_MP_RSZ_OUTPUT_WIDTH 4416
+#define STREAM_MAX_MP_RSZ_OUTPUT_HEIGHT3312
+#define STREAM_MAX_SP_RSZ_OUTPUT_WIDTH 1920
+#define STREAM_MAX_SP_RSZ_OUTPUT_HEIGHT1920
+#define STREAM_MIN_RSZ_OUTPUT_WIDTH32
+#define STREAM_MIN_RSZ_OUTPUT_HEIGHT   16
+
+#define STREAM_MAX_MP_SP_INPUT_WIDTH STREAM_MAX_MP_RSZ_OUTPUT_WIDTH
+#define STREAM_MAX_MP_SP_INPUT_HEIGHT STREAM_MAX_MP_RSZ_OUTPUT_HEIGHT
+#define STREAM_MIN_MP_SP_INPUT_WIDTH   32
+#define STREAM_MIN_MP_SP_INPUT_HEIGHT  32
+
+/* Get xsubs and ysubs for fourcc formats
+ *
+ * @xsubs: horizontal color samples in a 4*4 matrix, for yuv
+ * @ysubs: vertical color samples in a 4*4 matrix, for yuv
+ */
+static int fcc_xysubs(u32 fcc, u32 *xsubs, u32 *ysubs)
+{
+   switch (fcc) {
+   case V4L2_PIX_FMT_GREY:
+   case V4L2_PIX_FMT_YUV444M:
+   *xsubs = 1;
+   *ysubs = 1;
+   break;
+   case V4L2_PIX_FMT_YUYV:
+   case V4L2_PIX_FMT_YVYU:
+   case V4L2_PIX_FMT_VYUY:
+   case V4L2_PIX_FMT_YUV422P:
+   case V4L2_PIX_FMT_NV16:
+   case V4L2_PIX_FMT_NV61:
+   case V4L2_PIX_FMT_YVU422M:
+   *xsubs = 2;
+   *ysubs = 1;
+   break;
+   case V4L2_PIX_FMT_NV21:

[PATCH v5 02/16] media: doc: add document for rkisp1 meta buffer format

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen 

This commit add docuemnt for rkisp1 meta buffer format

Signed-off-by: Jacob Chen 
---
 Documentation/media/uapi/v4l/meta-formats.rst  |  2 ++
 .../media/uapi/v4l/pixfmt-meta-rkisp1-params.rst   | 17 +
 .../media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst | 18 ++
 3 files changed, 37 insertions(+)
 create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
 create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst

diff --git a/Documentation/media/uapi/v4l/meta-formats.rst 
b/Documentation/media/uapi/v4l/meta-formats.rst
index 01e24e3..1b82814 100644
--- a/Documentation/media/uapi/v4l/meta-formats.rst
+++ b/Documentation/media/uapi/v4l/meta-formats.rst
@@ -14,3 +14,5 @@ These formats are used for the :ref:`metadata` interface only.
 
 pixfmt-meta-vsp1-hgo
 pixfmt-meta-vsp1-hgt
+pixfmt-meta-rkisp1-params
+pixfmt-meta-rkisp1-stat
diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst 
b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
new file mode 100644
index 000..ed344d4
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
@@ -0,0 +1,17 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-meta-fmt-rkisp1-params:
+
+***
+V4L2_META_FMT_RK_ISP1_PARAMS
+***
+
+Rockchip ISP1 Parameters Data
+
+Description
+===
+
+This format describes input parameters for the Rockchip ISP1.
+
+The data use c-struct :c:type:`rkisp1_isp_params_cfg`, which is defined in
+the ``linux/rkisp1-config.h`` header file, See it for details.
diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst 
b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
new file mode 100644
index 000..5ecc403
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
@@ -0,0 +1,18 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-meta-fmt-rkisp1-stat:
+
+***
+V4L2_META_FMT_RK_ISP1_STAT_3A
+***
+
+Rockchip ISP1 Statistics Data
+
+Description
+===
+
+This format describes image color statistics information generated by the 
Rockchip
+ISP1.
+
+The data use c-struct :c:type:`rkisp1_stat_buffer`, which is defined in
+the ``linux/cifisp_stat.h`` header file, See it for details.
-- 
1.9.1



[PATCH v5 12/16] ARM: dts: rockchip: add isp node for rk3288

2017-12-28 Thread Shunqian Zheng
From: Jacob Chen 

rk3288 have a Embedded 13M ISP

Signed-off-by: Jacob Chen 
---
 arch/arm/boot/dts/rk3288.dtsi | 17 +
 1 file changed, 17 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index cd24894..5dbfafb 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -962,6 +962,23 @@
status = "disabled";
};
 
+   isp: isp@ff91 {
+   compatible = "rockchip,rk3288-cif-isp";
+   reg = <0x0 0xff91 0x0 0x4000>;
+   interrupts = ;
+   clocks = < SCLK_ISP>, < ACLK_ISP>,
+< HCLK_ISP>, < PCLK_ISP_IN>,
+< SCLK_ISP_JPE>;
+   clock-names = "clk_isp", "aclk_isp",
+ "hclk_isp", "pclk_isp_in",
+ "sclk_isp_jpe";
+   assigned-clocks = < SCLK_ISP>, < SCLK_ISP_JPE>;
+   assigned-clock-rates = <4>, <4>;
+   power-domains = < RK3288_PD_VIO>;
+   iommus = <_mmu>;
+   status = "disabled";
+   };
+
isp_mmu: iommu@ff914000 {
compatible = "rockchip,iommu";
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;
-- 
1.9.1



[PATCH v5 03/16] media: rkisp1: Add user space ABI definitions

2017-12-28 Thread Shunqian Zheng
From: Jeffy Chen 

Add the header for userspace

Signed-off-by: Jeffy Chen 
Signed-off-by: Jacob Chen 
---
 include/uapi/linux/rkisp1-config.h | 757 +
 1 file changed, 757 insertions(+)
 create mode 100644 include/uapi/linux/rkisp1-config.h

diff --git a/include/uapi/linux/rkisp1-config.h 
b/include/uapi/linux/rkisp1-config.h
new file mode 100644
index 000..0f9f4226
--- /dev/null
+++ b/include/uapi/linux/rkisp1-config.h
@@ -0,0 +1,757 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Rockchip isp1 driver
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef _UAPI_RKISP1_CONFIG_H
+#define _UAPI_RKISP1_CONFIG_H
+
+#include 
+#include 
+
+#define CIFISP_MODULE_DPCC  (1 << 0)
+#define CIFISP_MODULE_BLS   (1 << 1)
+#define CIFISP_MODULE_SDG   (1 << 2)
+#define CIFISP_MODULE_HST   (1 << 3)
+#define CIFISP_MODULE_LSC   (1 << 4)
+#define CIFISP_MODULE_AWB_GAIN  (1 << 5)
+#define CIFISP_MODULE_FLT   (1 << 6)
+#define CIFISP_MODULE_BDM   (1 << 7)
+#define CIFISP_MODULE_CTK   (1 << 8)
+#define CIFISP_MODULE_GOC   (1 << 9)
+#define CIFISP_MODULE_CPROC (1 << 10)
+#define CIFISP_MODULE_AFC   (1 << 11)
+#define CIFISP_MODULE_AWB   (1 << 12)
+#define CIFISP_MODULE_IE(1 << 13)
+#define CIFISP_MODULE_AEC   (1 << 14)
+#define CIFISP_MODULE_WDR   (1 << 15)
+#define CIFISP_MODULE_DPF   (1 << 16)
+#define CIFISP_MODULE_DPF_STRENGTH  (1 << 17)
+
+#define CIFISP_CTK_COEFF_MAX0x100
+#define CIFISP_CTK_OFFSET_MAX   0x800
+
+#define CIFISP_AE_MEAN_MAX  25
+#define CIFISP_HIST_BIN_N_MAX   16
+#define CIFISP_AFM_MAX_WINDOWS  3
+#define CIFISP_DEGAMMA_CURVE_SIZE   17
+
+#define CIFISP_BDM_MAX_TH   0xFF
+
+/*
+ * Black level compensation
+ */
+/* maximum value for horizontal start address */
+#define CIFISP_BLS_START_H_MAX 0x0FFF
+/* maximum value for horizontal stop address */
+#define CIFISP_BLS_STOP_H_MAX  0x0FFF
+/* maximum value for vertical start address */
+#define CIFISP_BLS_START_V_MAX 0x0FFF
+/* maximum value for vertical stop address */
+#define CIFISP_BLS_STOP_V_MAX  0x0FFF
+/* maximum is 2^18 = 262144*/
+#define CIFISP_BLS_SAMPLES_MAX 0x0012
+/* maximum value for fixed black level */
+#define CIFISP_BLS_FIX_SUB_MAX 0x0FFF
+/* minimum value for fixed black level */
+#define CIFISP_BLS_FIX_SUB_MIN 0xF000
+/* 13 bit range (signed)*/
+#define CIFISP_BLS_FIX_MASK0x1FFF
+
+/*
+ * Automatic white balance measurments
+ */
+#define CIFISP_AWB_MAX_GRID1
+#define CIFISP_AWB_MAX_FRAMES  7
+
+/*
+ * Gamma out
+ */
+/* Maximum number of color samples supported */
+#define CIFISP_GAMMA_OUT_MAX_SAMPLES   17
+
+/*
+ * Lens shade correction
+ */
+#define CIFISP_LSC_GRAD_TBL_SIZE   8
+#define CIFISP_LSC_SIZE_TBL_SIZE   8
+/*
+ * The following matches the tuning process,
+ * not the max capabilities of the chip.
+ * Last value unused.
+ */
+#defineCIFISP_LSC_DATA_TBL_SIZE   290
+
+/*
+ * Histogram calculation
+ */
+/* Last 3 values unused. */
+#define CIFISP_HISTOGRAM_WEIGHT_GRIDS_SIZE 28
+
+/*
+ * Defect Pixel Cluster Correction
+ */
+#define CIFISP_DPCC_METHODS_MAX   3
+
+/*
+ * Denoising pre filter
+ */
+#define CIFISP_DPF_MAX_NLF_COEFFS  17
+#define CIFISP_DPF_MAX_SPATIAL_COEFFS  6
+
+/*
+ * Measurement types
+ */
+#define CIFISP_STAT_AWB   (1 << 0)
+#define CIFISP_STAT_AUTOEXP   (1 << 1)
+#define CIFISP_STAT_AFM_FIN   (1 << 2)
+#define CIFISP_STAT_HIST  (1 << 3)
+
+enum cifisp_histogram_mode {
+   CIFISP_HISTOGRAM_MODE_DISABLE,
+   CIFISP_HISTOGRAM_MODE_RGB_COMBINED,
+   CIFISP_HISTOGRAM_MODE_R_HISTOGRAM,
+   CIFISP_HISTOGRAM_MODE_G_HISTOGRAM,
+   CIFISP_HISTOGRAM_MODE_B_HISTOGRAM,
+   CIFISP_HISTOGRAM_MODE_Y_HISTOGRAM
+};
+
+enum cifisp_awb_mode_type {
+   CIFISP_AWB_MODE_MANUAL,
+   CIFISP_AWB_MODE_RGB,
+   CIFISP_AWB_MODE_YCBCR
+};
+
+enum cifisp_flt_mode {
+   CIFISP_FLT_STATIC_MODE,
+   CIFISP_FLT_DYNAMIC_MODE
+};
+
+/**
+ * enum cifisp_exp_ctrl_auotostop - stop modes
+ * @CIFISP_EXP_CTRL_AUTOSTOP_0: continous measurement
+ * @CIFISP_EXP_CTRL_AUTOSTOP_1: stop measuring after a complete frame
+ */
+enum cifisp_exp_ctrl_auotostop {
+   CIFISP_EXP_CTRL_AUTOSTOP_0 = 0,
+   CIFISP_EXP_CTRL_AUTOSTOP_1 = 1,
+};
+
+/**
+ * enum cifisp_exp_meas_mode - Exposure measure mode
+ * @CIFISP_EXP_MEASURING_MODE_0: Y = 16 + 0.25R + 0.5G + 0.1094B
+ * @CIFISP_EXP_MEASURING_MODE_1: Y = (R + G + B) x (85/256)
+ */
+enum cifisp_exp_meas_mode {
+   CIFISP_EXP_MEASURING_MODE_0,
+   CIFISP_EXP_MEASURING_MODE_1,
+};
+
+/*-- PART1: Input 

[PATCH] clk: rockchip: add 2016M to big cpu clk rate table

2016-08-31 Thread Shunqian Zheng
We would prefer the 2016M as 2.0G than 1992M which seems odd, adding
it to big cpu clk rate table then we can set 2016M in dts.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
---
 drivers/clk/rockchip/clk-rk3399.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/rockchip/clk-rk3399.c 
b/drivers/clk/rockchip/clk-rk3399.c
index ede6c47..a6a15c6 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -375,6 +375,7 @@ static struct rockchip_cpuclk_rate_table 
rk3399_cpuclkb_rates[] __initdata = {
RK3399_CPUCLKB_RATE(218400, 1, 11, 11),
RK3399_CPUCLKB_RATE(208800, 1, 10, 10),
RK3399_CPUCLKB_RATE(204000, 1, 10, 10),
+   RK3399_CPUCLKB_RATE(201600, 1, 9, 9),
RK3399_CPUCLKB_RATE(199200, 1, 9, 9),
RK3399_CPUCLKB_RATE(189600, 1, 9, 9),
RK3399_CPUCLKB_RATE(18, 1, 8, 8),
-- 
1.9.1



[PATCH] clk: rockchip: add 2016M to big cpu clk rate table

2016-08-31 Thread Shunqian Zheng
We would prefer the 2016M as 2.0G than 1992M which seems odd, adding
it to big cpu clk rate table then we can set 2016M in dts.

Signed-off-by: Shunqian Zheng 
---
 drivers/clk/rockchip/clk-rk3399.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/rockchip/clk-rk3399.c 
b/drivers/clk/rockchip/clk-rk3399.c
index ede6c47..a6a15c6 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -375,6 +375,7 @@ static struct rockchip_cpuclk_rate_table 
rk3399_cpuclkb_rates[] __initdata = {
RK3399_CPUCLKB_RATE(218400, 1, 11, 11),
RK3399_CPUCLKB_RATE(208800, 1, 10, 10),
RK3399_CPUCLKB_RATE(204000, 1, 10, 10),
+   RK3399_CPUCLKB_RATE(201600, 1, 9, 9),
RK3399_CPUCLKB_RATE(199200, 1, 9, 9),
RK3399_CPUCLKB_RATE(189600, 1, 9, 9),
RK3399_CPUCLKB_RATE(18, 1, 8, 8),
-- 
1.9.1



[PATCH v5 3/8] iommu/rockchip: Fix allocation of bases array in driver probe

2016-06-23 Thread Shunqian Zheng
In .probe(), devm_kzalloc() is called with size == 0 and works only
by luck, due to internal behavior of the allocator and the fact
that the proper allocation size is small. Let's use proper value for
calculating the size.

Fixes: cd6438c5f844 ("iommu/rockchip: Reconstruct to support multi slaves")

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Tomasz Figa <tf...@chromium.org>
Reviewed-by: Douglas Anderson <diand...@chromium.org>
---
 drivers/iommu/rockchip-iommu.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 53fa0d9..8a5bac7 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1034,6 +1034,7 @@ static int rk_iommu_probe(struct platform_device *pdev)
struct device *dev = >dev;
struct rk_iommu *iommu;
struct resource *res;
+   int num_res = pdev->num_resources;
int i;
 
iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
@@ -1043,12 +1044,13 @@ static int rk_iommu_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, iommu);
iommu->dev = dev;
iommu->num_mmu = 0;
-   iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * iommu->num_mmu,
+
+   iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * num_res,
GFP_KERNEL);
if (!iommu->bases)
return -ENOMEM;
 
-   for (i = 0; i < pdev->num_resources; i++) {
+   for (i = 0; i < num_res; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res)
continue;
-- 
1.9.1



[PATCH v5 3/8] iommu/rockchip: Fix allocation of bases array in driver probe

2016-06-23 Thread Shunqian Zheng
In .probe(), devm_kzalloc() is called with size == 0 and works only
by luck, due to internal behavior of the allocator and the fact
that the proper allocation size is small. Let's use proper value for
calculating the size.

Fixes: cd6438c5f844 ("iommu/rockchip: Reconstruct to support multi slaves")

Signed-off-by: Shunqian Zheng 
Signed-off-by: Tomasz Figa 
Reviewed-by: Douglas Anderson 
---
 drivers/iommu/rockchip-iommu.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 53fa0d9..8a5bac7 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1034,6 +1034,7 @@ static int rk_iommu_probe(struct platform_device *pdev)
struct device *dev = >dev;
struct rk_iommu *iommu;
struct resource *res;
+   int num_res = pdev->num_resources;
int i;
 
iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
@@ -1043,12 +1044,13 @@ static int rk_iommu_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, iommu);
iommu->dev = dev;
iommu->num_mmu = 0;
-   iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * iommu->num_mmu,
+
+   iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * num_res,
GFP_KERNEL);
if (!iommu->bases)
return -ENOMEM;
 
-   for (i = 0; i < pdev->num_resources; i++) {
+   for (i = 0; i < num_res; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res)
continue;
-- 
1.9.1



[PATCH v5 8/8] iommu/rockchip: Enable Rockchip IOMMU on ARM64

2016-06-23 Thread Shunqian Zheng
From: Simon Xue <x...@rock-chips.com>

This patch makes it possible to compile the rockchip-iommu driver on
ARM64, so that it can be used with 64-bit SoCs equipped with this type
of IOMMU.

Signed-off-by: Simon Xue <x...@rock-chips.com>
Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/iommu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index ad08603..5572621 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -218,7 +218,7 @@ config OMAP_IOMMU_DEBUG
 
 config ROCKCHIP_IOMMU
bool "Rockchip IOMMU Support"
-   depends on ARM
+   depends on ARM || ARM64
depends on ARCH_ROCKCHIP || COMPILE_TEST
select IOMMU_API
select ARM_DMA_USE_IOMMU
-- 
1.9.1



[PATCH v5 6/8] drm/rockchip: Do not use DMA mapping API if attached to IOMMU domain

2016-06-23 Thread Shunqian Zheng
From: Tomasz Figa <tf...@chromium.org>

The API is not suitable for subsystems consisting of multiple devices
and requires severe hacks to use it. To mitigate this, this patch
implements allocation and address space management locally by using
helpers provided by DRM framework, like other DRM drivers do, e.g.
Tegra.

This patch should not introduce any functional changes until the driver
is made to attach subdevices into an IOMMU domain with the generic IOMMU
API, which will happen in following patch. Based heavily on GEM
implementation of Tegra DRM driver.

Signed-off-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
 drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 221 ++--
 drivers/gpu/drm/rockchip/rockchip_drm_gem.h |   9 ++
 3 files changed, 222 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index ea39329..5ab1223 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -30,6 +30,7 @@
 
 struct drm_device;
 struct drm_connector;
+struct iommu_domain;
 
 /*
  * Rockchip drm private crtc funcs.
@@ -61,6 +62,8 @@ struct rockchip_drm_private {
struct drm_gem_object *fbdev_bo;
const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
struct drm_atomic_state *state;
+   struct iommu_domain *domain;
+   struct drm_mm mm;
 };
 
 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index 394f92b..e7cd93d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -19,11 +19,135 @@
 #include 
 
 #include 
+#include 
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_gem.h"
 
-static int rockchip_gem_alloc_buf(struct rockchip_gem_object *rk_obj,
+static int rockchip_gem_iommu_map(struct rockchip_gem_object *rk_obj)
+{
+   struct drm_device *drm = rk_obj->base.dev;
+   struct rockchip_drm_private *private = drm->dev_private;
+   int prot = IOMMU_READ | IOMMU_WRITE;
+   ssize_t ret;
+
+   ret = drm_mm_insert_node_generic(>mm, _obj->mm,
+rk_obj->base.size, PAGE_SIZE,
+0, 0, 0);
+   if (ret < 0) {
+   DRM_ERROR("out of I/O virtual memory: %zd\n", ret);
+   return ret;
+   }
+
+   rk_obj->dma_addr = rk_obj->mm.start;
+
+   ret = iommu_map_sg(private->domain, rk_obj->dma_addr, rk_obj->sgt->sgl,
+  rk_obj->sgt->nents, prot);
+   if (ret < 0) {
+   DRM_ERROR("failed to map buffer: %zd\n", ret);
+   goto err_remove_node;
+   }
+
+   rk_obj->size = ret;
+
+   return 0;
+
+err_remove_node:
+   drm_mm_remove_node(_obj->mm);
+
+   return ret;
+}
+
+static int rockchip_gem_iommu_unmap(struct rockchip_gem_object *rk_obj)
+{
+   struct drm_device *drm = rk_obj->base.dev;
+   struct rockchip_drm_private *private = drm->dev_private;
+
+   iommu_unmap(private->domain, rk_obj->dma_addr, rk_obj->size);
+   drm_mm_remove_node(_obj->mm);
+
+   return 0;
+}
+
+static int rockchip_gem_get_pages(struct rockchip_gem_object *rk_obj)
+{
+   struct drm_device *drm = rk_obj->base.dev;
+   int ret, i;
+   struct scatterlist *s;
+
+   rk_obj->pages = drm_gem_get_pages(_obj->base);
+   if (IS_ERR(rk_obj->pages))
+   return PTR_ERR(rk_obj->pages);
+
+   rk_obj->num_pages = rk_obj->base.size >> PAGE_SHIFT;
+
+   rk_obj->sgt = drm_prime_pages_to_sg(rk_obj->pages, rk_obj->num_pages);
+   if (IS_ERR(rk_obj->sgt)) {
+   ret = PTR_ERR(rk_obj->sgt);
+   goto err_put_pages;
+   }
+
+   /*
+* Fake up the SG table so that dma_sync_sg_for_device() can be used
+* to flush the pages associated with it.
+*
+* TODO: Replace this by drm_clflush_sg() once it can be implemented
+* without relying on symbols that are not exported.
+*/
+   for_each_sg(rk_obj->sgt->sgl, s, rk_obj->sgt->nents, i)
+   sg_dma_address(s) = sg_phys(s);
+
+   dma_sync_sg_for_device(drm->dev, rk_obj->sgt->sgl, rk_obj->sgt->nents,
+  DMA_TO_DEVICE);
+
+   return 0;
+
+err_put_pages:
+   drm_gem_put_pages(_obj->base, rk_obj->pages, false, false);
+   return ret;
+}
+
+static void rockchip_gem_put_pages(struct rockchip_gem_object *rk_obj)
+{
+   sg_free_table(rk_obj->sgt);
+   kfree(rk_obj->sgt);
+   d

[PATCH v5 8/8] iommu/rockchip: Enable Rockchip IOMMU on ARM64

2016-06-23 Thread Shunqian Zheng
From: Simon Xue 

This patch makes it possible to compile the rockchip-iommu driver on
ARM64, so that it can be used with 64-bit SoCs equipped with this type
of IOMMU.

Signed-off-by: Simon Xue 
Signed-off-by: Shunqian Zheng 
Signed-off-by: Tomasz Figa 
---
 drivers/iommu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index ad08603..5572621 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -218,7 +218,7 @@ config OMAP_IOMMU_DEBUG
 
 config ROCKCHIP_IOMMU
bool "Rockchip IOMMU Support"
-   depends on ARM
+   depends on ARM || ARM64
depends on ARCH_ROCKCHIP || COMPILE_TEST
select IOMMU_API
select ARM_DMA_USE_IOMMU
-- 
1.9.1



[PATCH v5 6/8] drm/rockchip: Do not use DMA mapping API if attached to IOMMU domain

2016-06-23 Thread Shunqian Zheng
From: Tomasz Figa 

The API is not suitable for subsystems consisting of multiple devices
and requires severe hacks to use it. To mitigate this, this patch
implements allocation and address space management locally by using
helpers provided by DRM framework, like other DRM drivers do, e.g.
Tegra.

This patch should not introduce any functional changes until the driver
is made to attach subdevices into an IOMMU domain with the generic IOMMU
API, which will happen in following patch. Based heavily on GEM
implementation of Tegra DRM driver.

Signed-off-by: Tomasz Figa 
Signed-off-by: Shunqian Zheng 
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
 drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 221 ++--
 drivers/gpu/drm/rockchip/rockchip_drm_gem.h |   9 ++
 3 files changed, 222 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index ea39329..5ab1223 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -30,6 +30,7 @@
 
 struct drm_device;
 struct drm_connector;
+struct iommu_domain;
 
 /*
  * Rockchip drm private crtc funcs.
@@ -61,6 +62,8 @@ struct rockchip_drm_private {
struct drm_gem_object *fbdev_bo;
const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
struct drm_atomic_state *state;
+   struct iommu_domain *domain;
+   struct drm_mm mm;
 };
 
 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index 394f92b..e7cd93d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -19,11 +19,135 @@
 #include 
 
 #include 
+#include 
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_gem.h"
 
-static int rockchip_gem_alloc_buf(struct rockchip_gem_object *rk_obj,
+static int rockchip_gem_iommu_map(struct rockchip_gem_object *rk_obj)
+{
+   struct drm_device *drm = rk_obj->base.dev;
+   struct rockchip_drm_private *private = drm->dev_private;
+   int prot = IOMMU_READ | IOMMU_WRITE;
+   ssize_t ret;
+
+   ret = drm_mm_insert_node_generic(>mm, _obj->mm,
+rk_obj->base.size, PAGE_SIZE,
+0, 0, 0);
+   if (ret < 0) {
+   DRM_ERROR("out of I/O virtual memory: %zd\n", ret);
+   return ret;
+   }
+
+   rk_obj->dma_addr = rk_obj->mm.start;
+
+   ret = iommu_map_sg(private->domain, rk_obj->dma_addr, rk_obj->sgt->sgl,
+  rk_obj->sgt->nents, prot);
+   if (ret < 0) {
+   DRM_ERROR("failed to map buffer: %zd\n", ret);
+   goto err_remove_node;
+   }
+
+   rk_obj->size = ret;
+
+   return 0;
+
+err_remove_node:
+   drm_mm_remove_node(_obj->mm);
+
+   return ret;
+}
+
+static int rockchip_gem_iommu_unmap(struct rockchip_gem_object *rk_obj)
+{
+   struct drm_device *drm = rk_obj->base.dev;
+   struct rockchip_drm_private *private = drm->dev_private;
+
+   iommu_unmap(private->domain, rk_obj->dma_addr, rk_obj->size);
+   drm_mm_remove_node(_obj->mm);
+
+   return 0;
+}
+
+static int rockchip_gem_get_pages(struct rockchip_gem_object *rk_obj)
+{
+   struct drm_device *drm = rk_obj->base.dev;
+   int ret, i;
+   struct scatterlist *s;
+
+   rk_obj->pages = drm_gem_get_pages(_obj->base);
+   if (IS_ERR(rk_obj->pages))
+   return PTR_ERR(rk_obj->pages);
+
+   rk_obj->num_pages = rk_obj->base.size >> PAGE_SHIFT;
+
+   rk_obj->sgt = drm_prime_pages_to_sg(rk_obj->pages, rk_obj->num_pages);
+   if (IS_ERR(rk_obj->sgt)) {
+   ret = PTR_ERR(rk_obj->sgt);
+   goto err_put_pages;
+   }
+
+   /*
+* Fake up the SG table so that dma_sync_sg_for_device() can be used
+* to flush the pages associated with it.
+*
+* TODO: Replace this by drm_clflush_sg() once it can be implemented
+* without relying on symbols that are not exported.
+*/
+   for_each_sg(rk_obj->sgt->sgl, s, rk_obj->sgt->nents, i)
+   sg_dma_address(s) = sg_phys(s);
+
+   dma_sync_sg_for_device(drm->dev, rk_obj->sgt->sgl, rk_obj->sgt->nents,
+  DMA_TO_DEVICE);
+
+   return 0;
+
+err_put_pages:
+   drm_gem_put_pages(_obj->base, rk_obj->pages, false, false);
+   return ret;
+}
+
+static void rockchip_gem_put_pages(struct rockchip_gem_object *rk_obj)
+{
+   sg_free_table(rk_obj->sgt);
+   kfree(rk_obj->sgt);
+   drm_gem_put_pages(_obj->base, rk_obj->pages, false, false);
+}
+
+static int rockc

[PATCH v5 4/8] iommu/rockchip: Use DMA API to manage coherency

2016-06-23 Thread Shunqian Zheng
Use DMA API instead of architecture internal functions like
__cpuc_flush_dcache_area() etc.

The biggest difficulty here is that dma_map and _sync calls require some
struct device, while there is no real 1:1 relation between an IOMMU
domain and some device. To overcome this, a simple platform device is
registered for each allocated IOMMU domain.

With this patch, this driver can be used on both ARM and ARM64
platforms, such as RK3288 and RK3399 respectively.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/iommu/rockchip-iommu.c | 162 +++--
 1 file changed, 123 insertions(+), 39 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 8a5bac7..712ed75 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -4,11 +4,10 @@
  * published by the Free Software Foundation.
  */
 
-#include 
-#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -77,7 +76,9 @@
 
 struct rk_iommu_domain {
struct list_head iommus;
+   struct platform_device *pdev;
u32 *dt; /* page directory table */
+   dma_addr_t dt_dma;
spinlock_t iommus_lock; /* lock for iommus list */
spinlock_t dt_lock; /* lock for modifying page directory table */
 
@@ -93,14 +94,12 @@ struct rk_iommu {
struct iommu_domain *domain; /* domain to which iommu is attached */
 };
 
-static inline void rk_table_flush(u32 *va, unsigned int count)
+static inline void rk_table_flush(struct rk_iommu_domain *dom, dma_addr_t dma,
+ unsigned int count)
 {
-   phys_addr_t pa_start = virt_to_phys(va);
-   phys_addr_t pa_end = virt_to_phys(va + count);
-   size_t size = pa_end - pa_start;
+   size_t size = count * sizeof(u32); /* count of u32 entry */
 
-   __cpuc_flush_dcache_area(va, size);
-   outer_flush_range(pa_start, pa_end);
+   dma_sync_single_for_device(>pdev->dev, dma, size, DMA_TO_DEVICE);
 }
 
 static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
@@ -183,10 +182,9 @@ static inline bool rk_dte_is_pt_valid(u32 dte)
return dte & RK_DTE_PT_VALID;
 }
 
-static u32 rk_mk_dte(u32 *pt)
+static inline u32 rk_mk_dte(dma_addr_t pt_dma)
 {
-   phys_addr_t pt_phys = virt_to_phys(pt);
-   return (pt_phys & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
+   return (pt_dma & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
 }
 
 /*
@@ -603,13 +601,16 @@ static void rk_iommu_zap_iova_first_last(struct 
rk_iommu_domain *rk_domain,
 static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain,
  dma_addr_t iova)
 {
+   struct device *dev = _domain->pdev->dev;
u32 *page_table, *dte_addr;
-   u32 dte;
+   u32 dte_index, dte;
phys_addr_t pt_phys;
+   dma_addr_t pt_dma;
 
assert_spin_locked(_domain->dt_lock);
 
-   dte_addr = _domain->dt[rk_iova_dte_index(iova)];
+   dte_index = rk_iova_dte_index(iova);
+   dte_addr = _domain->dt[dte_index];
dte = *dte_addr;
if (rk_dte_is_pt_valid(dte))
goto done;
@@ -618,19 +619,27 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
if (!page_table)
return ERR_PTR(-ENOMEM);
 
-   dte = rk_mk_dte(page_table);
-   *dte_addr = dte;
+   pt_dma = dma_map_single(dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
+   if (dma_mapping_error(dev, pt_dma)) {
+   dev_err(dev, "DMA mapping error while allocating page table\n");
+   free_page((unsigned long)page_table);
+   return ERR_PTR(-ENOMEM);
+   }
 
-   rk_table_flush(page_table, NUM_PT_ENTRIES);
-   rk_table_flush(dte_addr, 1);
+   dte = rk_mk_dte(pt_dma);
+   *dte_addr = dte;
 
+   rk_table_flush(rk_domain, pt_dma, NUM_PT_ENTRIES);
+   rk_table_flush(rk_domain,
+  rk_domain->dt_dma + dte_index * sizeof(u32), 1);
 done:
pt_phys = rk_dte_pt_address(dte);
return (u32 *)phys_to_virt(pt_phys);
 }
 
 static size_t rk_iommu_unmap_iova(struct rk_iommu_domain *rk_domain,
- u32 *pte_addr, dma_addr_t iova, size_t size)
+ u32 *pte_addr, dma_addr_t pte_dma,
+ size_t size)
 {
unsigned int pte_count;
unsigned int pte_total = size / SPAGE_SIZE;
@@ -645,14 +654,14 @@ static size_t rk_iommu_unmap_iova(struct rk_iommu_domain 
*rk_domain,
pte_addr[pte_count] = rk_mk_pte_invalid(pte);
}
 
-   rk_table_flush(pte_addr, pte_count);
+   rk_table_flush(rk_domain, pte_dma, pte_count);
 
return pte_count * SPAGE_SIZE;
 }
 
 static int rk_iommu_map_iova(struct rk_iommu_domain *rk_domain, u32 *pte_addr,
-

[PATCH v5 4/8] iommu/rockchip: Use DMA API to manage coherency

2016-06-23 Thread Shunqian Zheng
Use DMA API instead of architecture internal functions like
__cpuc_flush_dcache_area() etc.

The biggest difficulty here is that dma_map and _sync calls require some
struct device, while there is no real 1:1 relation between an IOMMU
domain and some device. To overcome this, a simple platform device is
registered for each allocated IOMMU domain.

With this patch, this driver can be used on both ARM and ARM64
platforms, such as RK3288 and RK3399 respectively.

Signed-off-by: Shunqian Zheng 
Signed-off-by: Tomasz Figa 
---
 drivers/iommu/rockchip-iommu.c | 162 +++--
 1 file changed, 123 insertions(+), 39 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 8a5bac7..712ed75 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -4,11 +4,10 @@
  * published by the Free Software Foundation.
  */
 
-#include 
-#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -77,7 +76,9 @@
 
 struct rk_iommu_domain {
struct list_head iommus;
+   struct platform_device *pdev;
u32 *dt; /* page directory table */
+   dma_addr_t dt_dma;
spinlock_t iommus_lock; /* lock for iommus list */
spinlock_t dt_lock; /* lock for modifying page directory table */
 
@@ -93,14 +94,12 @@ struct rk_iommu {
struct iommu_domain *domain; /* domain to which iommu is attached */
 };
 
-static inline void rk_table_flush(u32 *va, unsigned int count)
+static inline void rk_table_flush(struct rk_iommu_domain *dom, dma_addr_t dma,
+ unsigned int count)
 {
-   phys_addr_t pa_start = virt_to_phys(va);
-   phys_addr_t pa_end = virt_to_phys(va + count);
-   size_t size = pa_end - pa_start;
+   size_t size = count * sizeof(u32); /* count of u32 entry */
 
-   __cpuc_flush_dcache_area(va, size);
-   outer_flush_range(pa_start, pa_end);
+   dma_sync_single_for_device(>pdev->dev, dma, size, DMA_TO_DEVICE);
 }
 
 static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
@@ -183,10 +182,9 @@ static inline bool rk_dte_is_pt_valid(u32 dte)
return dte & RK_DTE_PT_VALID;
 }
 
-static u32 rk_mk_dte(u32 *pt)
+static inline u32 rk_mk_dte(dma_addr_t pt_dma)
 {
-   phys_addr_t pt_phys = virt_to_phys(pt);
-   return (pt_phys & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
+   return (pt_dma & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
 }
 
 /*
@@ -603,13 +601,16 @@ static void rk_iommu_zap_iova_first_last(struct 
rk_iommu_domain *rk_domain,
 static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain,
  dma_addr_t iova)
 {
+   struct device *dev = _domain->pdev->dev;
u32 *page_table, *dte_addr;
-   u32 dte;
+   u32 dte_index, dte;
phys_addr_t pt_phys;
+   dma_addr_t pt_dma;
 
assert_spin_locked(_domain->dt_lock);
 
-   dte_addr = _domain->dt[rk_iova_dte_index(iova)];
+   dte_index = rk_iova_dte_index(iova);
+   dte_addr = _domain->dt[dte_index];
dte = *dte_addr;
if (rk_dte_is_pt_valid(dte))
goto done;
@@ -618,19 +619,27 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
if (!page_table)
return ERR_PTR(-ENOMEM);
 
-   dte = rk_mk_dte(page_table);
-   *dte_addr = dte;
+   pt_dma = dma_map_single(dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
+   if (dma_mapping_error(dev, pt_dma)) {
+   dev_err(dev, "DMA mapping error while allocating page table\n");
+   free_page((unsigned long)page_table);
+   return ERR_PTR(-ENOMEM);
+   }
 
-   rk_table_flush(page_table, NUM_PT_ENTRIES);
-   rk_table_flush(dte_addr, 1);
+   dte = rk_mk_dte(pt_dma);
+   *dte_addr = dte;
 
+   rk_table_flush(rk_domain, pt_dma, NUM_PT_ENTRIES);
+   rk_table_flush(rk_domain,
+  rk_domain->dt_dma + dte_index * sizeof(u32), 1);
 done:
pt_phys = rk_dte_pt_address(dte);
return (u32 *)phys_to_virt(pt_phys);
 }
 
 static size_t rk_iommu_unmap_iova(struct rk_iommu_domain *rk_domain,
- u32 *pte_addr, dma_addr_t iova, size_t size)
+ u32 *pte_addr, dma_addr_t pte_dma,
+ size_t size)
 {
unsigned int pte_count;
unsigned int pte_total = size / SPAGE_SIZE;
@@ -645,14 +654,14 @@ static size_t rk_iommu_unmap_iova(struct rk_iommu_domain 
*rk_domain,
pte_addr[pte_count] = rk_mk_pte_invalid(pte);
}
 
-   rk_table_flush(pte_addr, pte_count);
+   rk_table_flush(rk_domain, pte_dma, pte_count);
 
return pte_count * SPAGE_SIZE;
 }
 
 static int rk_iommu_map_iova(struct rk_iommu_domain *rk_domain, u32 *pte_addr,
-dma_addr_t iova, phys_addr_t paddr, size

[PATCH v5 7/8] drm/rockchip: Use common IOMMU API to attach devices

2016-06-23 Thread Shunqian Zheng
Rockchip DRM used the arm special API, arm_iommu_*(), to attach
iommu for ARM32 SoCs. This patch convert to common iommu API
so it would support ARM64 like RK3399.

Since previous patch added support for direct IOMMU address space
management, there is no need to use DMA API anymore and this patch wires
things to use the new method.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 100 +++-
 1 file changed, 53 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 8b96c69..ca9624f 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -14,18 +14,18 @@
  * GNU General Public License for more details.
  */
 
-#include 
-
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -51,28 +51,31 @@ static struct drm_driver rockchip_drm_driver;
 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev)
 {
-   struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
+   struct rockchip_drm_private *private = drm_dev->dev_private;
int ret;
 
if (!is_support_iommu)
return 0;
 
-   ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
-   if (ret)
+   ret = iommu_attach_device(private->domain, dev);
+   if (ret) {
+   dev_err(dev, "Failed to attach iommu device\n");
return ret;
+   }
 
-   dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
-
-   return arm_iommu_attach_device(dev, mapping);
+   return 0;
 }
 
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev)
 {
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain *domain = private->domain;
+
if (!is_support_iommu)
return;
 
-   arm_iommu_detach_device(dev);
+   iommu_detach_device(domain, dev);
 }
 
 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
@@ -137,11 +140,45 @@ static void rockchip_drm_crtc_disable_vblank(struct 
drm_device *dev,
priv->crtc_funcs[pipe]->disable_vblank(crtc);
 }
 
+static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain_geometry *geometry;
+   u64 start, end;
+
+   if (!is_support_iommu)
+   return 0;
+
+   private->domain = iommu_domain_alloc(_bus_type);
+   if (!private->domain)
+   return -ENOMEM;
+
+   geometry = >domain->geometry;
+   start = geometry->aperture_start;
+   end = geometry->aperture_end;
+
+   DRM_DEBUG("IOMMU context initialized (aperture: %#llx-%#llx)\n",
+ start, end);
+   drm_mm_init(>mm, start, end - start + 1);
+
+   return 0;
+}
+
+static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+
+   if (!is_support_iommu)
+   return;
+
+   drm_mm_takedown(>mm);
+   iommu_domain_free(private->domain);
+}
+
 static int rockchip_drm_bind(struct device *dev)
 {
struct drm_device *drm_dev;
struct rockchip_drm_private *private;
-   struct dma_iommu_mapping *mapping = NULL;
int ret;
 
drm_dev = drm_dev_alloc(_drm_driver, dev);
@@ -162,38 +199,14 @@ static int rockchip_drm_bind(struct device *dev)
 
rockchip_drm_mode_config_init(drm_dev);
 
-   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
- GFP_KERNEL);
-   if (!dev->dma_parms) {
-   ret = -ENOMEM;
+   ret = rockchip_drm_init_iommu(drm_dev);
+   if (ret)
goto err_config_cleanup;
-   }
-
-   if (is_support_iommu) {
-   /* TODO(djkurtz): fetch the mapping start/size from somewhere */
-   mapping = arm_iommu_create_mapping(_bus_type,
-  0x,
-  SZ_2G);
-   if (IS_ERR(mapping)) {
-   ret = PTR_ERR(mapping);
-   goto err_config_cleanup;
-   }
-
-   ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
-   if (ret)
-   goto err_release_mapping;
-
-   dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
-
-   ret = arm_iommu_attach_device(dev, mapping);
-   if (ret)
-   goto err_release_mapping;
- 

[PATCH v5 2/8] iommu/rockchip: Add map_sg callback for rk_iommu_ops

2016-06-23 Thread Shunqian Zheng
From: Simon Xue <x...@rock-chips.com>

The iommu_dma_alloc() in iommu/dma-iommu.c calls iommu_map_sg()
that requires the callback iommu_ops .map_sg(). Adding the
default_iommu_map_sg() to Rockchip IOMMU accordingly.

Signed-off-by: Simon Xue <x...@rock-chips.com>
Signed-off-by: Shunqian Zheng <x...@rock-chips.com>
Reviewed-by: Douglas Anderson <diand...@chromium.org>
Signed-off-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/iommu/rockchip-iommu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 5a9659a..53fa0d9 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1022,6 +1022,7 @@ static const struct iommu_ops rk_iommu_ops = {
.detach_dev = rk_iommu_detach_device,
.map = rk_iommu_map,
.unmap = rk_iommu_unmap,
+   .map_sg = default_iommu_map_sg,
.add_device = rk_iommu_add_device,
.remove_device = rk_iommu_remove_device,
.iova_to_phys = rk_iommu_iova_to_phys,
-- 
1.9.1



[PATCH v5 5/8] iommu/rockchip: Prepare to support generic DMA mapping

2016-06-23 Thread Shunqian Zheng
Set geometry for allocated domains and fix .domain_alloc() callback to
work with IOMMU_DOMAIN_DMA domain type, which is used for implicit
domains on ARM64.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Signed-off-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/iommu/rockchip-iommu.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 712ed75..9afcbf7 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -889,7 +889,7 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned 
type)
struct platform_device *pdev;
struct device *iommu_dev;
 
-   if (type != IOMMU_DOMAIN_UNMANAGED)
+   if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
return NULL;
 
/* Register a pdev per domain, so DMA API can base on this *dev
@@ -906,8 +906,8 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned 
type)
 
rk_domain->pdev = pdev;
 
-   /* To init the iovad which is required by iommu_dma_init_domain() */
-   if (iommu_get_dma_cookie(_domain->domain))
+   if (type == IOMMU_DOMAIN_DMA &&
+   iommu_get_dma_cookie(_domain->domain))
goto err_unreg_pdev;
 
/*
@@ -933,12 +933,17 @@ static struct iommu_domain 
*rk_iommu_domain_alloc(unsigned type)
spin_lock_init(_domain->dt_lock);
INIT_LIST_HEAD(_domain->iommus);
 
+   rk_domain->domain.geometry.aperture_start = 0;
+   rk_domain->domain.geometry.aperture_end   = DMA_BIT_MASK(32);
+   rk_domain->domain.geometry.force_aperture = true;
+
return _domain->domain;
 
 err_free_dt:
free_page((unsigned long)rk_domain->dt);
 err_put_cookie:
-   iommu_put_dma_cookie(_domain->domain);
+   if (type == IOMMU_DOMAIN_DMA)
+   iommu_put_dma_cookie(_domain->domain);
 err_unreg_pdev:
platform_device_unregister(pdev);
 
@@ -967,7 +972,8 @@ static void rk_iommu_domain_free(struct iommu_domain 
*domain)
 SPAGE_SIZE, DMA_TO_DEVICE);
free_page((unsigned long)rk_domain->dt);
 
-   iommu_put_dma_cookie(_domain->domain);
+   if (domain->type == IOMMU_DOMAIN_DMA)
+   iommu_put_dma_cookie(_domain->domain);
 
platform_device_unregister(rk_domain->pdev);
 }
-- 
1.9.1



[PATCH v5 7/8] drm/rockchip: Use common IOMMU API to attach devices

2016-06-23 Thread Shunqian Zheng
Rockchip DRM used the arm special API, arm_iommu_*(), to attach
iommu for ARM32 SoCs. This patch convert to common iommu API
so it would support ARM64 like RK3399.

Since previous patch added support for direct IOMMU address space
management, there is no need to use DMA API anymore and this patch wires
things to use the new method.

Signed-off-by: Shunqian Zheng 
Signed-off-by: Tomasz Figa 
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 100 +++-
 1 file changed, 53 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 8b96c69..ca9624f 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -14,18 +14,18 @@
  * GNU General Public License for more details.
  */
 
-#include 
-
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -51,28 +51,31 @@ static struct drm_driver rockchip_drm_driver;
 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev)
 {
-   struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
+   struct rockchip_drm_private *private = drm_dev->dev_private;
int ret;
 
if (!is_support_iommu)
return 0;
 
-   ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
-   if (ret)
+   ret = iommu_attach_device(private->domain, dev);
+   if (ret) {
+   dev_err(dev, "Failed to attach iommu device\n");
return ret;
+   }
 
-   dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
-
-   return arm_iommu_attach_device(dev, mapping);
+   return 0;
 }
 
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev)
 {
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain *domain = private->domain;
+
if (!is_support_iommu)
return;
 
-   arm_iommu_detach_device(dev);
+   iommu_detach_device(domain, dev);
 }
 
 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
@@ -137,11 +140,45 @@ static void rockchip_drm_crtc_disable_vblank(struct 
drm_device *dev,
priv->crtc_funcs[pipe]->disable_vblank(crtc);
 }
 
+static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain_geometry *geometry;
+   u64 start, end;
+
+   if (!is_support_iommu)
+   return 0;
+
+   private->domain = iommu_domain_alloc(_bus_type);
+   if (!private->domain)
+   return -ENOMEM;
+
+   geometry = >domain->geometry;
+   start = geometry->aperture_start;
+   end = geometry->aperture_end;
+
+   DRM_DEBUG("IOMMU context initialized (aperture: %#llx-%#llx)\n",
+ start, end);
+   drm_mm_init(>mm, start, end - start + 1);
+
+   return 0;
+}
+
+static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+
+   if (!is_support_iommu)
+   return;
+
+   drm_mm_takedown(>mm);
+   iommu_domain_free(private->domain);
+}
+
 static int rockchip_drm_bind(struct device *dev)
 {
struct drm_device *drm_dev;
struct rockchip_drm_private *private;
-   struct dma_iommu_mapping *mapping = NULL;
int ret;
 
drm_dev = drm_dev_alloc(_drm_driver, dev);
@@ -162,38 +199,14 @@ static int rockchip_drm_bind(struct device *dev)
 
rockchip_drm_mode_config_init(drm_dev);
 
-   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
- GFP_KERNEL);
-   if (!dev->dma_parms) {
-   ret = -ENOMEM;
+   ret = rockchip_drm_init_iommu(drm_dev);
+   if (ret)
goto err_config_cleanup;
-   }
-
-   if (is_support_iommu) {
-   /* TODO(djkurtz): fetch the mapping start/size from somewhere */
-   mapping = arm_iommu_create_mapping(_bus_type,
-  0x,
-  SZ_2G);
-   if (IS_ERR(mapping)) {
-   ret = PTR_ERR(mapping);
-   goto err_config_cleanup;
-   }
-
-   ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
-   if (ret)
-   goto err_release_mapping;
-
-   dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
-
-   ret = arm_iommu_attach_device(dev, mapping);
-   if (ret)
-   goto err_release_mapping;
-   }
 
/* Try to bind all sub drivers. */

[PATCH v5 2/8] iommu/rockchip: Add map_sg callback for rk_iommu_ops

2016-06-23 Thread Shunqian Zheng
From: Simon Xue 

The iommu_dma_alloc() in iommu/dma-iommu.c calls iommu_map_sg()
that requires the callback iommu_ops .map_sg(). Adding the
default_iommu_map_sg() to Rockchip IOMMU accordingly.

Signed-off-by: Simon Xue 
Signed-off-by: Shunqian Zheng 
Reviewed-by: Douglas Anderson 
Signed-off-by: Tomasz Figa 
---
 drivers/iommu/rockchip-iommu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 5a9659a..53fa0d9 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1022,6 +1022,7 @@ static const struct iommu_ops rk_iommu_ops = {
.detach_dev = rk_iommu_detach_device,
.map = rk_iommu_map,
.unmap = rk_iommu_unmap,
+   .map_sg = default_iommu_map_sg,
.add_device = rk_iommu_add_device,
.remove_device = rk_iommu_remove_device,
.iova_to_phys = rk_iommu_iova_to_phys,
-- 
1.9.1



[PATCH v5 5/8] iommu/rockchip: Prepare to support generic DMA mapping

2016-06-23 Thread Shunqian Zheng
Set geometry for allocated domains and fix .domain_alloc() callback to
work with IOMMU_DOMAIN_DMA domain type, which is used for implicit
domains on ARM64.

Signed-off-by: Shunqian Zheng 
Signed-off-by: Tomasz Figa 
---
 drivers/iommu/rockchip-iommu.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 712ed75..9afcbf7 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -889,7 +889,7 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned 
type)
struct platform_device *pdev;
struct device *iommu_dev;
 
-   if (type != IOMMU_DOMAIN_UNMANAGED)
+   if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
return NULL;
 
/* Register a pdev per domain, so DMA API can base on this *dev
@@ -906,8 +906,8 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned 
type)
 
rk_domain->pdev = pdev;
 
-   /* To init the iovad which is required by iommu_dma_init_domain() */
-   if (iommu_get_dma_cookie(_domain->domain))
+   if (type == IOMMU_DOMAIN_DMA &&
+   iommu_get_dma_cookie(_domain->domain))
goto err_unreg_pdev;
 
/*
@@ -933,12 +933,17 @@ static struct iommu_domain 
*rk_iommu_domain_alloc(unsigned type)
spin_lock_init(_domain->dt_lock);
INIT_LIST_HEAD(_domain->iommus);
 
+   rk_domain->domain.geometry.aperture_start = 0;
+   rk_domain->domain.geometry.aperture_end   = DMA_BIT_MASK(32);
+   rk_domain->domain.geometry.force_aperture = true;
+
return _domain->domain;
 
 err_free_dt:
free_page((unsigned long)rk_domain->dt);
 err_put_cookie:
-   iommu_put_dma_cookie(_domain->domain);
+   if (type == IOMMU_DOMAIN_DMA)
+   iommu_put_dma_cookie(_domain->domain);
 err_unreg_pdev:
platform_device_unregister(pdev);
 
@@ -967,7 +972,8 @@ static void rk_iommu_domain_free(struct iommu_domain 
*domain)
 SPAGE_SIZE, DMA_TO_DEVICE);
free_page((unsigned long)rk_domain->dt);
 
-   iommu_put_dma_cookie(_domain->domain);
+   if (domain->type == IOMMU_DOMAIN_DMA)
+   iommu_put_dma_cookie(_domain->domain);
 
platform_device_unregister(rk_domain->pdev);
 }
-- 
1.9.1



iommu/rockchip: Fix bugs and enable on ARM64

2016-06-23 Thread Shunqian Zheng
This series intends mostly to enable support for ARM64 architecture
in the rockchip-iommu driver. On the way to do so, some bugs are also
fixed.

The most important changes here are:
 - making the Rockchip IOMMU driver use DMA API for managing cache
   coherency of page tables,
 - making the Rockchip DRM driver not use DMA API on behalf of a virtual
   device (behind a virtual IOMMU) to allocate and map buffers, but
   instead proper DRM helpers and IOMMU API directly.

Changes since v4:
 - Address some coding style comments on:
- https://chromium-review.googlesource.com/#/c/346328/38
- https://chromium-review.googlesource.com/#/c/353591/10
Changes since v3:
 - Drop the idea of virtual IOMMU. Instead replace hacky allocation code
   in DRM driver, with proper management of IOMMU domain.
 - Add one more fix for allocation of IOMMU register base addresses.
Changes since v2:
 - Instead of registering virtual IOMMU from DTS, create it when
   attaching.
 - Fix some bugs found in internal review.

Shunqian Zheng (4):
  iommu/rockchip: Fix allocation of bases array in driver probe
  iommu/rockchip: Use DMA API to manage coherency
  iommu/rockchip: Prepare to support generic DMA mapping
  drm/rockchip: Use common IOMMU API to attach devices

Simon Xue (3):
  iommu/rockchip: Fix devm_{request,free}_irq parameter
  iommu/rockchip: Add map_sg callback for rk_iommu_ops
  iommu/rockchip: Enable Rockchip IOMMU on ARM64

Tomasz Figa (1):
  drm/rockchip: Do not use DMA mapping API if attached to IOMMU domain

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 100 +++--
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
 drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 221 ++--
 drivers/gpu/drm/rockchip/rockchip_drm_gem.h |   9 ++
 drivers/iommu/Kconfig   |   2 +-
 drivers/iommu/rockchip-iommu.c  | 181 +--
 6 files changed, 413 insertions(+), 103 deletions(-)

-- 
1.9.1



iommu/rockchip: Fix bugs and enable on ARM64

2016-06-23 Thread Shunqian Zheng
This series intends mostly to enable support for ARM64 architecture
in the rockchip-iommu driver. On the way to do so, some bugs are also
fixed.

The most important changes here are:
 - making the Rockchip IOMMU driver use DMA API for managing cache
   coherency of page tables,
 - making the Rockchip DRM driver not use DMA API on behalf of a virtual
   device (behind a virtual IOMMU) to allocate and map buffers, but
   instead proper DRM helpers and IOMMU API directly.

Changes since v4:
 - Address some coding style comments on:
- https://chromium-review.googlesource.com/#/c/346328/38
- https://chromium-review.googlesource.com/#/c/353591/10
Changes since v3:
 - Drop the idea of virtual IOMMU. Instead replace hacky allocation code
   in DRM driver, with proper management of IOMMU domain.
 - Add one more fix for allocation of IOMMU register base addresses.
Changes since v2:
 - Instead of registering virtual IOMMU from DTS, create it when
   attaching.
 - Fix some bugs found in internal review.

Shunqian Zheng (4):
  iommu/rockchip: Fix allocation of bases array in driver probe
  iommu/rockchip: Use DMA API to manage coherency
  iommu/rockchip: Prepare to support generic DMA mapping
  drm/rockchip: Use common IOMMU API to attach devices

Simon Xue (3):
  iommu/rockchip: Fix devm_{request,free}_irq parameter
  iommu/rockchip: Add map_sg callback for rk_iommu_ops
  iommu/rockchip: Enable Rockchip IOMMU on ARM64

Tomasz Figa (1):
  drm/rockchip: Do not use DMA mapping API if attached to IOMMU domain

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 100 +++--
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
 drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 221 ++--
 drivers/gpu/drm/rockchip/rockchip_drm_gem.h |   9 ++
 drivers/iommu/Kconfig   |   2 +-
 drivers/iommu/rockchip-iommu.c  | 181 +--
 6 files changed, 413 insertions(+), 103 deletions(-)

-- 
1.9.1



[PATCH v5 1/8] iommu/rockchip: Fix devm_{request,free}_irq parameter

2016-06-23 Thread Shunqian Zheng
From: Simon Xue <x...@rock-chips.com>

Even though the IOMMU shares IRQ with its master, the struct device
passed to {request,free}_irq is supposed to represent the device that is
signalling the interrupt. This patch makes the driver use IOMMU device
instead of master's device to make things clear.

Signed-off-by: Simon Xue <x...@rock-chips.com>
Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Reviewed-by: Douglas Anderson <diand...@chromium.org>
Signed-off-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/iommu/rockchip-iommu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 25b4627..5a9659a 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -807,7 +807,7 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
iommu->domain = domain;
 
-   ret = devm_request_irq(dev, iommu->irq, rk_iommu_irq,
+   ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq,
   IRQF_SHARED, dev_name(dev), iommu);
if (ret)
return ret;
@@ -860,7 +860,7 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
}
rk_iommu_disable_stall(iommu);
 
-   devm_free_irq(dev, iommu->irq, iommu);
+   devm_free_irq(iommu->dev, iommu->irq, iommu);
 
iommu->domain = NULL;
 
-- 
1.9.1



[PATCH v5 1/8] iommu/rockchip: Fix devm_{request,free}_irq parameter

2016-06-23 Thread Shunqian Zheng
From: Simon Xue 

Even though the IOMMU shares IRQ with its master, the struct device
passed to {request,free}_irq is supposed to represent the device that is
signalling the interrupt. This patch makes the driver use IOMMU device
instead of master's device to make things clear.

Signed-off-by: Simon Xue 
Signed-off-by: Shunqian Zheng 
Reviewed-by: Douglas Anderson 
Signed-off-by: Tomasz Figa 
---
 drivers/iommu/rockchip-iommu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 25b4627..5a9659a 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -807,7 +807,7 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
iommu->domain = domain;
 
-   ret = devm_request_irq(dev, iommu->irq, rk_iommu_irq,
+   ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq,
   IRQF_SHARED, dev_name(dev), iommu);
if (ret)
return ret;
@@ -860,7 +860,7 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
}
rk_iommu_disable_stall(iommu);
 
-   devm_free_irq(dev, iommu->irq, iommu);
+   devm_free_irq(iommu->dev, iommu->irq, iommu);
 
iommu->domain = NULL;
 
-- 
1.9.1



[PATCH v3 3/6] iommu/rockchip: support virtual iommu slave device

2016-06-15 Thread Shunqian Zheng
An virtual master device like DRM need to attach to iommu
domain to share the mapping with VOPs(the one with actual
iommu slaves).
DRM attaches to iommu and allocates buffers before VOPs enabled,
which means there may have not real iommu devices can be used
to do dma mapping.

This patch creates a iommu when virtual master(group is NULL)
attaching, so it can use this iommu even the real iommus disabled.

Changes of V3:
- Instead of registering virtual iommu in DTS, this patch
  creates a iommu when attaching.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Suggested-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/iommu/rockchip-iommu.c | 133 +
 1 file changed, 122 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 3c16ec3..82ecc99 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -93,6 +94,14 @@ struct rk_iommu {
struct iommu_domain *domain; /* domain to which iommu is attached */
 };
 
+/* A virtual iommu registered without resource or
+ * interrupts when DRM attaching.
+ */
+static inline bool rk_iommu_is_virtual(struct rk_iommu *iommu)
+{
+   return iommu->num_mmu == 0;
+}
+
 static inline void rk_table_flush(u32 *va, unsigned int count)
 {
phys_addr_t pa_start = virt_to_phys(va);
@@ -780,6 +789,85 @@ static struct rk_iommu *rk_iommu_from_dev(struct device 
*dev)
return rk_iommu;
 }
 
+static struct rk_iommu *rk_iommu_add_virtual_iommu(struct device *dev,
+   struct rk_iommu_domain *rk_domain)
+{
+   struct rk_iommu *iommu;
+   struct iommu_group *group;
+   struct platform_device *pdev;
+   struct device *iommu_dev;
+   int ret;
+
+   pdev = platform_device_register_simple("rk_iommu", PLATFORM_DEVID_AUTO,
+  NULL, 0);
+   if (IS_ERR(pdev)) {
+   dev_err(dev, "Failed to register simple rk_iommu device\n");
+   return NULL;
+   }
+
+   iommu_dev = >dev;
+   iommu_dev->dma_parms = devm_kzalloc(iommu_dev,
+   sizeof(*iommu_dev->dma_parms), GFP_KERNEL);
+   if (!iommu_dev->dma_parms)
+   goto err_unreg_pdev;
+
+   /* Set dma_ops for virtual iommu, otherwise it would be dummy_dma_ops */
+   arch_setup_dma_ops(iommu_dev, 0, DMA_BIT_MASK(32), NULL, false);
+
+   dma_set_max_seg_size(iommu_dev, DMA_BIT_MASK(32));
+   dma_coerce_mask_and_coherent(iommu_dev, DMA_BIT_MASK(32));
+
+   iommu = devm_kzalloc(iommu_dev, sizeof(*iommu), GFP_KERNEL);
+   if (!iommu)
+   goto err_unreg_pdev;
+
+   iommu->dev = iommu_dev;
+   iommu->num_mmu = 0;
+   platform_set_drvdata(pdev, iommu);
+
+   group = iommu_group_alloc();
+   if (IS_ERR(group)) {
+   dev_err(iommu_dev, "Failed to allocate IOMMU group\n");
+   goto err_unreg_pdev;
+   }
+
+   ret = iommu_group_add_device(group, dev);
+   if (ret) {
+   dev_err(iommu_dev, "Failed to add device to group\n");
+   goto err_put_group;
+   }
+
+   iommu_group_set_iommudata(group, iommu_dev, NULL);
+
+   ret = iommu_attach_group(_domain->domain, group);
+   if (ret) {
+   dev_err(iommu_dev, "Failed to attach group\n");
+   goto err_remove_device;
+   }
+
+   iommu_group_put(group);
+
+   return iommu;
+
+err_remove_device:
+   iommu_group_remove_device(dev);
+err_put_group:
+   iommu_group_put(group);
+err_unreg_pdev:
+   platform_device_unregister(pdev);
+
+   return NULL;
+}
+
+static void rk_iommu_remove_virtual_iommu(struct device *dev)
+{
+   struct rk_iommu *iommu = rk_iommu_from_dev(dev);
+   struct platform_device *pdev = to_platform_device(iommu->dev);
+
+   iommu_group_remove_device(dev);
+   platform_device_unregister(pdev);
+}
+
 static int rk_iommu_attach_device(struct iommu_domain *domain,
  struct device *dev)
 {
@@ -789,13 +877,20 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
int ret, i;
phys_addr_t dte_addr;
 
-   /*
-* Allow 'virtual devices' (e.g., drm) to attach to domain.
-* Such a device does not belong to an iommu group.
-*/
iommu = rk_iommu_from_dev(dev);
-   if (!iommu)
+
+   /* Register iommu for virtual master(like DRM) */
+   if (!iommu) {
+   iommu = rk_iommu_add_virtual_iommu(dev, rk_domain);
+   if (!iommu)
+   return -ENOMEM;
+   }
+
+   iommu->domain = domain;
+   if (rk_iommu_is_virtual(iommu)) {
+   dev_dbg(dev, &

[PATCH v3 5/6] iommu/rockchip: use DMA API to map, to flush cache

2016-06-15 Thread Shunqian Zheng
Use DMA API instead of architecture internal functions like
__cpuc_flush_dcache_area() etc.

To support the virtual device like DRM the virtual slave iommu
added in the previous patch, attaching to which the DRM can use
it own domain->dev for dma_map_*(), dma_sync_*() even VOP is disabled.

With this patch, this driver is available for ARM64 like RK3399.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
---
 drivers/iommu/rockchip-iommu.c | 113 +++--
 1 file changed, 76 insertions(+), 37 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 82ecc99..b60b29e 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -4,8 +4,6 @@
  * published by the Free Software Foundation.
  */
 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -78,7 +76,9 @@
 
 struct rk_iommu_domain {
struct list_head iommus;
+   struct device *dev;
u32 *dt; /* page directory table */
+   dma_addr_t dt_dma;
spinlock_t iommus_lock; /* lock for iommus list */
spinlock_t dt_lock; /* lock for modifying page directory table */
 
@@ -102,14 +102,12 @@ static inline bool rk_iommu_is_virtual(struct rk_iommu 
*iommu)
return iommu->num_mmu == 0;
 }
 
-static inline void rk_table_flush(u32 *va, unsigned int count)
+static inline void rk_table_flush(struct device *dev, dma_addr_t dma,
+ unsigned int count)
 {
-   phys_addr_t pa_start = virt_to_phys(va);
-   phys_addr_t pa_end = virt_to_phys(va + count);
-   size_t size = pa_end - pa_start;
+   size_t size = count * 4; /* count of entry, 4 bytes per entry */
 
-   __cpuc_flush_dcache_area(va, size);
-   outer_flush_range(pa_start, pa_end);
+   dma_sync_single_for_device(dev, dma, size, DMA_TO_DEVICE);
 }
 
 static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
@@ -192,10 +190,9 @@ static inline bool rk_dte_is_pt_valid(u32 dte)
return dte & RK_DTE_PT_VALID;
 }
 
-static u32 rk_mk_dte(u32 *pt)
+static inline u32 rk_mk_dte(dma_addr_t pt_dma)
 {
-   phys_addr_t pt_phys = virt_to_phys(pt);
-   return (pt_phys & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
+   return (pt_dma & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
 }
 
 /*
@@ -613,12 +610,14 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
  dma_addr_t iova)
 {
u32 *page_table, *dte_addr;
-   u32 dte;
+   u32 dte_index, dte;
phys_addr_t pt_phys;
+   dma_addr_t pt_dma;
 
assert_spin_locked(_domain->dt_lock);
 
-   dte_addr = _domain->dt[rk_iova_dte_index(iova)];
+   dte_index = rk_iova_dte_index(iova);
+   dte_addr = _domain->dt[dte_index];
dte = *dte_addr;
if (rk_dte_is_pt_valid(dte))
goto done;
@@ -627,19 +626,28 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
if (!page_table)
return ERR_PTR(-ENOMEM);
 
-   dte = rk_mk_dte(page_table);
-   *dte_addr = dte;
+   pt_dma = dma_map_single(rk_domain->dev, page_table,
+   SPAGE_SIZE, DMA_TO_DEVICE);
+   if (dma_mapping_error(rk_domain->dev, pt_dma)) {
+   dev_err(rk_domain->dev,
+   "DMA mapping error while allocating page table\n");
+   free_page((unsigned long)page_table);
+   return ERR_PTR(-ENOMEM);
+   }
 
-   rk_table_flush(page_table, NUM_PT_ENTRIES);
-   rk_table_flush(dte_addr, 1);
+   dte = rk_mk_dte(pt_dma);
+   *dte_addr = dte;
 
+   rk_table_flush(rk_domain->dev, pt_dma, NUM_PT_ENTRIES);
+   rk_table_flush(rk_domain->dev, rk_domain->dt_dma + dte_index * 4, 1);
 done:
pt_phys = rk_dte_pt_address(dte);
return (u32 *)phys_to_virt(pt_phys);
 }
 
 static size_t rk_iommu_unmap_iova(struct rk_iommu_domain *rk_domain,
- u32 *pte_addr, dma_addr_t iova, size_t size)
+ u32 *pte_addr, dma_addr_t pte_dma,
+ size_t size)
 {
unsigned int pte_count;
unsigned int pte_total = size / SPAGE_SIZE;
@@ -654,14 +662,14 @@ static size_t rk_iommu_unmap_iova(struct rk_iommu_domain 
*rk_domain,
pte_addr[pte_count] = rk_mk_pte_invalid(pte);
}
 
-   rk_table_flush(pte_addr, pte_count);
+   rk_table_flush(rk_domain->dev, pte_dma, pte_count);
 
return pte_count * SPAGE_SIZE;
 }
 
 static int rk_iommu_map_iova(struct rk_iommu_domain *rk_domain, u32 *pte_addr,
-dma_addr_t iova, phys_addr_t paddr, size_t size,
-int prot)
+dma_addr_t pte_dma, dma_addr_t iova,
+phys_addr_t paddr, size_t size, int prot)
 {
unsigned i

[PATCH v3 3/6] iommu/rockchip: support virtual iommu slave device

2016-06-15 Thread Shunqian Zheng
An virtual master device like DRM need to attach to iommu
domain to share the mapping with VOPs(the one with actual
iommu slaves).
DRM attaches to iommu and allocates buffers before VOPs enabled,
which means there may have not real iommu devices can be used
to do dma mapping.

This patch creates a iommu when virtual master(group is NULL)
attaching, so it can use this iommu even the real iommus disabled.

Changes of V3:
- Instead of registering virtual iommu in DTS, this patch
  creates a iommu when attaching.

Signed-off-by: Shunqian Zheng 
Suggested-by: Tomasz Figa 
---
 drivers/iommu/rockchip-iommu.c | 133 +
 1 file changed, 122 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 3c16ec3..82ecc99 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -93,6 +94,14 @@ struct rk_iommu {
struct iommu_domain *domain; /* domain to which iommu is attached */
 };
 
+/* A virtual iommu registered without resource or
+ * interrupts when DRM attaching.
+ */
+static inline bool rk_iommu_is_virtual(struct rk_iommu *iommu)
+{
+   return iommu->num_mmu == 0;
+}
+
 static inline void rk_table_flush(u32 *va, unsigned int count)
 {
phys_addr_t pa_start = virt_to_phys(va);
@@ -780,6 +789,85 @@ static struct rk_iommu *rk_iommu_from_dev(struct device 
*dev)
return rk_iommu;
 }
 
+static struct rk_iommu *rk_iommu_add_virtual_iommu(struct device *dev,
+   struct rk_iommu_domain *rk_domain)
+{
+   struct rk_iommu *iommu;
+   struct iommu_group *group;
+   struct platform_device *pdev;
+   struct device *iommu_dev;
+   int ret;
+
+   pdev = platform_device_register_simple("rk_iommu", PLATFORM_DEVID_AUTO,
+  NULL, 0);
+   if (IS_ERR(pdev)) {
+   dev_err(dev, "Failed to register simple rk_iommu device\n");
+   return NULL;
+   }
+
+   iommu_dev = >dev;
+   iommu_dev->dma_parms = devm_kzalloc(iommu_dev,
+   sizeof(*iommu_dev->dma_parms), GFP_KERNEL);
+   if (!iommu_dev->dma_parms)
+   goto err_unreg_pdev;
+
+   /* Set dma_ops for virtual iommu, otherwise it would be dummy_dma_ops */
+   arch_setup_dma_ops(iommu_dev, 0, DMA_BIT_MASK(32), NULL, false);
+
+   dma_set_max_seg_size(iommu_dev, DMA_BIT_MASK(32));
+   dma_coerce_mask_and_coherent(iommu_dev, DMA_BIT_MASK(32));
+
+   iommu = devm_kzalloc(iommu_dev, sizeof(*iommu), GFP_KERNEL);
+   if (!iommu)
+   goto err_unreg_pdev;
+
+   iommu->dev = iommu_dev;
+   iommu->num_mmu = 0;
+   platform_set_drvdata(pdev, iommu);
+
+   group = iommu_group_alloc();
+   if (IS_ERR(group)) {
+   dev_err(iommu_dev, "Failed to allocate IOMMU group\n");
+   goto err_unreg_pdev;
+   }
+
+   ret = iommu_group_add_device(group, dev);
+   if (ret) {
+   dev_err(iommu_dev, "Failed to add device to group\n");
+   goto err_put_group;
+   }
+
+   iommu_group_set_iommudata(group, iommu_dev, NULL);
+
+   ret = iommu_attach_group(_domain->domain, group);
+   if (ret) {
+   dev_err(iommu_dev, "Failed to attach group\n");
+   goto err_remove_device;
+   }
+
+   iommu_group_put(group);
+
+   return iommu;
+
+err_remove_device:
+   iommu_group_remove_device(dev);
+err_put_group:
+   iommu_group_put(group);
+err_unreg_pdev:
+   platform_device_unregister(pdev);
+
+   return NULL;
+}
+
+static void rk_iommu_remove_virtual_iommu(struct device *dev)
+{
+   struct rk_iommu *iommu = rk_iommu_from_dev(dev);
+   struct platform_device *pdev = to_platform_device(iommu->dev);
+
+   iommu_group_remove_device(dev);
+   platform_device_unregister(pdev);
+}
+
 static int rk_iommu_attach_device(struct iommu_domain *domain,
  struct device *dev)
 {
@@ -789,13 +877,20 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
int ret, i;
phys_addr_t dte_addr;
 
-   /*
-* Allow 'virtual devices' (e.g., drm) to attach to domain.
-* Such a device does not belong to an iommu group.
-*/
iommu = rk_iommu_from_dev(dev);
-   if (!iommu)
+
+   /* Register iommu for virtual master(like DRM) */
+   if (!iommu) {
+   iommu = rk_iommu_add_virtual_iommu(dev, rk_domain);
+   if (!iommu)
+   return -ENOMEM;
+   }
+
+   iommu->domain = domain;
+   if (rk_iommu_is_virtual(iommu)) {
+   dev_dbg(dev, "Attach virtual device to iommu domain\n");
re

[PATCH v3 5/6] iommu/rockchip: use DMA API to map, to flush cache

2016-06-15 Thread Shunqian Zheng
Use DMA API instead of architecture internal functions like
__cpuc_flush_dcache_area() etc.

To support the virtual device like DRM the virtual slave iommu
added in the previous patch, attaching to which the DRM can use
it own domain->dev for dma_map_*(), dma_sync_*() even VOP is disabled.

With this patch, this driver is available for ARM64 like RK3399.

Signed-off-by: Shunqian Zheng 
---
 drivers/iommu/rockchip-iommu.c | 113 +++--
 1 file changed, 76 insertions(+), 37 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 82ecc99..b60b29e 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -4,8 +4,6 @@
  * published by the Free Software Foundation.
  */
 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -78,7 +76,9 @@
 
 struct rk_iommu_domain {
struct list_head iommus;
+   struct device *dev;
u32 *dt; /* page directory table */
+   dma_addr_t dt_dma;
spinlock_t iommus_lock; /* lock for iommus list */
spinlock_t dt_lock; /* lock for modifying page directory table */
 
@@ -102,14 +102,12 @@ static inline bool rk_iommu_is_virtual(struct rk_iommu 
*iommu)
return iommu->num_mmu == 0;
 }
 
-static inline void rk_table_flush(u32 *va, unsigned int count)
+static inline void rk_table_flush(struct device *dev, dma_addr_t dma,
+ unsigned int count)
 {
-   phys_addr_t pa_start = virt_to_phys(va);
-   phys_addr_t pa_end = virt_to_phys(va + count);
-   size_t size = pa_end - pa_start;
+   size_t size = count * 4; /* count of entry, 4 bytes per entry */
 
-   __cpuc_flush_dcache_area(va, size);
-   outer_flush_range(pa_start, pa_end);
+   dma_sync_single_for_device(dev, dma, size, DMA_TO_DEVICE);
 }
 
 static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
@@ -192,10 +190,9 @@ static inline bool rk_dte_is_pt_valid(u32 dte)
return dte & RK_DTE_PT_VALID;
 }
 
-static u32 rk_mk_dte(u32 *pt)
+static inline u32 rk_mk_dte(dma_addr_t pt_dma)
 {
-   phys_addr_t pt_phys = virt_to_phys(pt);
-   return (pt_phys & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
+   return (pt_dma & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
 }
 
 /*
@@ -613,12 +610,14 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
  dma_addr_t iova)
 {
u32 *page_table, *dte_addr;
-   u32 dte;
+   u32 dte_index, dte;
phys_addr_t pt_phys;
+   dma_addr_t pt_dma;
 
assert_spin_locked(_domain->dt_lock);
 
-   dte_addr = _domain->dt[rk_iova_dte_index(iova)];
+   dte_index = rk_iova_dte_index(iova);
+   dte_addr = _domain->dt[dte_index];
dte = *dte_addr;
if (rk_dte_is_pt_valid(dte))
goto done;
@@ -627,19 +626,28 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
if (!page_table)
return ERR_PTR(-ENOMEM);
 
-   dte = rk_mk_dte(page_table);
-   *dte_addr = dte;
+   pt_dma = dma_map_single(rk_domain->dev, page_table,
+   SPAGE_SIZE, DMA_TO_DEVICE);
+   if (dma_mapping_error(rk_domain->dev, pt_dma)) {
+   dev_err(rk_domain->dev,
+   "DMA mapping error while allocating page table\n");
+   free_page((unsigned long)page_table);
+   return ERR_PTR(-ENOMEM);
+   }
 
-   rk_table_flush(page_table, NUM_PT_ENTRIES);
-   rk_table_flush(dte_addr, 1);
+   dte = rk_mk_dte(pt_dma);
+   *dte_addr = dte;
 
+   rk_table_flush(rk_domain->dev, pt_dma, NUM_PT_ENTRIES);
+   rk_table_flush(rk_domain->dev, rk_domain->dt_dma + dte_index * 4, 1);
 done:
pt_phys = rk_dte_pt_address(dte);
return (u32 *)phys_to_virt(pt_phys);
 }
 
 static size_t rk_iommu_unmap_iova(struct rk_iommu_domain *rk_domain,
- u32 *pte_addr, dma_addr_t iova, size_t size)
+ u32 *pte_addr, dma_addr_t pte_dma,
+ size_t size)
 {
unsigned int pte_count;
unsigned int pte_total = size / SPAGE_SIZE;
@@ -654,14 +662,14 @@ static size_t rk_iommu_unmap_iova(struct rk_iommu_domain 
*rk_domain,
pte_addr[pte_count] = rk_mk_pte_invalid(pte);
}
 
-   rk_table_flush(pte_addr, pte_count);
+   rk_table_flush(rk_domain->dev, pte_dma, pte_count);
 
return pte_count * SPAGE_SIZE;
 }
 
 static int rk_iommu_map_iova(struct rk_iommu_domain *rk_domain, u32 *pte_addr,
-dma_addr_t iova, phys_addr_t paddr, size_t size,
-int prot)
+dma_addr_t pte_dma, dma_addr_t iova,
+phys_addr_t paddr, size_t size, int prot)
 {
unsigned int pte_count;
unsigned int

[PATCH v3 1/6] iommu/rockchip: fix devm_{request,free}_irq parameter

2016-06-15 Thread Shunqian Zheng
From: Simon Xue <x...@rock-chips.com>

Even though the iommu shares irq with its master, using the *dev of iommu
instead of master's *dev for devm_{request,free}_irq makes things clear.

Signed-off-by: Simon Xue <x...@rock-chips.com>
Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/iommu/rockchip-iommu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index c7d6156..ec0ce62 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -807,7 +807,7 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
iommu->domain = domain;
 
-   ret = devm_request_irq(dev, iommu->irq, rk_iommu_irq,
+   ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq,
   IRQF_SHARED, dev_name(dev), iommu);
if (ret)
return ret;
@@ -860,7 +860,7 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
}
rk_iommu_disable_stall(iommu);
 
-   devm_free_irq(dev, iommu->irq, iommu);
+   devm_free_irq(iommu->dev, iommu->irq, iommu);
 
iommu->domain = NULL;
 
-- 
1.9.1



[PATCH v3 1/6] iommu/rockchip: fix devm_{request,free}_irq parameter

2016-06-15 Thread Shunqian Zheng
From: Simon Xue 

Even though the iommu shares irq with its master, using the *dev of iommu
instead of master's *dev for devm_{request,free}_irq makes things clear.

Signed-off-by: Simon Xue 
Signed-off-by: Shunqian Zheng 
Reviewed-by: Tomasz Figa 
---
 drivers/iommu/rockchip-iommu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index c7d6156..ec0ce62 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -807,7 +807,7 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
iommu->domain = domain;
 
-   ret = devm_request_irq(dev, iommu->irq, rk_iommu_irq,
+   ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq,
   IRQF_SHARED, dev_name(dev), iommu);
if (ret)
return ret;
@@ -860,7 +860,7 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
}
rk_iommu_disable_stall(iommu);
 
-   devm_free_irq(dev, iommu->irq, iommu);
+   devm_free_irq(iommu->dev, iommu->irq, iommu);
 
iommu->domain = NULL;
 
-- 
1.9.1



[PATCH v3 2/6] iommu/rockchip: add map_sg callback for rk_iommu_ops

2016-06-15 Thread Shunqian Zheng
From: Simon Xue <x...@rock-chips.com>

The iommu_dma_alloc() in iommu/dma-iommu.c calls iommu_map_sg()
that requires the callback iommu_ops .map_sg(). Adding the
default_iommu_map_sg() to rockchip iommu accordingly.

Signed-off-by: Simon Xue <x...@rock-chips.com>
Signed-off-by: Shunqian Zheng <x...@rock-chips.com>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/iommu/rockchip-iommu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index ec0ce62..3c16ec3 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1022,6 +1022,7 @@ static const struct iommu_ops rk_iommu_ops = {
.detach_dev = rk_iommu_detach_device,
.map = rk_iommu_map,
.unmap = rk_iommu_unmap,
+   .map_sg = default_iommu_map_sg,
.add_device = rk_iommu_add_device,
.remove_device = rk_iommu_remove_device,
.iova_to_phys = rk_iommu_iova_to_phys,
-- 
1.9.1



[PATCH v3 6/6] iommu/rockchip: enable rockchip iommu on ARM64 platform

2016-06-15 Thread Shunqian Zheng
From: Simon Xue <x...@rock-chips.com>

This patch makes it possible to compile the rockchip-iommu driver on
ARM64 platform to be used with 64-bit SoCs equipped with this type
of IOMMU.

Signed-off-by: Simon Xue <x...@rock-chips.com>
Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
---
 drivers/iommu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index ad08603..5572621 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -218,7 +218,7 @@ config OMAP_IOMMU_DEBUG
 
 config ROCKCHIP_IOMMU
bool "Rockchip IOMMU Support"
-   depends on ARM
+   depends on ARM || ARM64
depends on ARCH_ROCKCHIP || COMPILE_TEST
select IOMMU_API
select ARM_DMA_USE_IOMMU
-- 
1.9.1



[PATCH v3 4/6] drm: rockchip: use common iommu api to attach iommu

2016-06-15 Thread Shunqian Zheng
Rockchip DRM used the arm special API, arm_iommu_*(), to attach
iommu for ARM32 SoCs. This patch convert to common iommu API
so it would support ARM64 like RK3399.

The general idea is domain_alloc(), attach_device() and
arch_setup_dma_ops() to set dma_ops manually for DRM at the last.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 112 +---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 +
 2 files changed, 71 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index f5a68fc..b52c38d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -14,16 +14,16 @@
  * GNU General Public License for more details.
  */
 
-#include 
-
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_fb.h"
@@ -46,7 +46,8 @@ static bool is_support_iommu = true;
 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev)
 {
-   struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain *domain = private->domain;
int ret;
 
if (!is_support_iommu)
@@ -58,16 +59,25 @@ int rockchip_drm_dma_attach_device(struct drm_device 
*drm_dev,
 
dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
 
-   return arm_iommu_attach_device(dev, mapping);
+   ret = iommu_attach_device(domain, dev);
+   if (ret) {
+   dev_err(dev, "Failed to attach iommu device\n");
+   return ret;
+   }
+
+   /* TODO(djkurtz): fetch the mapping start/size from somewhere */
+   arch_setup_dma_ops(dev, 0x, SZ_2G, dev->bus->iommu_ops, false);
+   return 0;
 }
 
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev)
 {
-   if (!is_support_iommu)
-   return;
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain *domain = private->domain;
 
-   arm_iommu_detach_device(dev);
+   if (is_support_iommu)
+   iommu_detach_device(domain, dev);
 }
 
 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
@@ -132,10 +142,52 @@ static void rockchip_drm_crtc_disable_vblank(struct 
drm_device *dev,
priv->crtc_funcs[pipe]->disable_vblank(crtc);
 }
 
+static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct device *dev = drm_dev->dev;
+   int ret;
+
+   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
+ GFP_KERNEL);
+   if (!dev->dma_parms)
+   return -ENOMEM;
+
+   private->domain = iommu_domain_alloc(_bus_type);
+   if (!private->domain)
+   return -ENOMEM;
+
+   /* TODO(djkurtz): fetch the mapping start/size from somewhere */
+   ret = iommu_dma_init_domain(private->domain, 0x, SZ_2G);
+   if (ret) {
+   dev_err(dev, "Failed to init domain\n");
+   goto err_free_domain;
+   }
+
+   ret = rockchip_drm_dma_attach_device(drm_dev, dev);
+   if (ret) {
+   dev_err(dev, "Failed to attach device\n");
+   goto err_free_domain;
+   }
+
+   return 0;
+
+err_free_domain:
+   iommu_domain_free(private->domain);
+
+   return ret;
+}
+
+static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+
+   iommu_domain_free(private->domain);
+}
+
 static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
 {
struct rockchip_drm_private *private;
-   struct dma_iommu_mapping *mapping = NULL;
struct device *dev = drm_dev->dev;
struct drm_connector *connector;
int ret;
@@ -153,38 +205,18 @@ static int rockchip_drm_load(struct drm_device *drm_dev, 
unsigned long flags)
 
rockchip_drm_mode_config_init(drm_dev);
 
-   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
- GFP_KERNEL);
-   if (!dev->dma_parms) {
-   ret = -ENOMEM;
-   goto err_config_cleanup;
-   }
-
if (is_support_iommu) {
-   /* TODO(djkurtz): fetch the mapping start/size from somewhere */
-   mapping = arm_iommu_create_mapping(_bus_type,
-  0x,
-  SZ_2G);
-  

[PATCH v3 0/6] fix bugs; enable iommu for ARM64

2016-06-15 Thread Shunqian Zheng
This series patches mainly for ARM64 supporting.
To do this, it first add virtual iommu slave device which DRM can attach to,
convert DRM driver to use common iommu API instead of the ARM32
functions, and then use DMA API in iommu driver to map, to flush cache.

Mainly changes of V3:
- Instead of registering virtual iommu in DTS, V3
  creates a iommu when attaching.
- Fix some bugs according to Tomasz's comments,
  most of them are offline, locally.

Shunqian Zheng (3):
  iommu/rockchip: support virtual iommu slave device
  drm: rockchip: use common iommu api to attach iommu
  iommu/rockchip: use DMA API to map, to flush cache

Simon Xue (3):
  iommu/rockchip: fix devm_{request,free}_irq parameter
  iommu/rockchip: add map_sg callback for rk_iommu_ops
  iommu/rockchip: enable rockchip iommu on ARM64 platform

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 112 -
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 +
 drivers/iommu/Kconfig   |   2 +-
 drivers/iommu/rockchip-iommu.c  | 251 ++--
 4 files changed, 273 insertions(+), 93 deletions(-)

-- 
1.9.1



[PATCH v3 2/6] iommu/rockchip: add map_sg callback for rk_iommu_ops

2016-06-15 Thread Shunqian Zheng
From: Simon Xue 

The iommu_dma_alloc() in iommu/dma-iommu.c calls iommu_map_sg()
that requires the callback iommu_ops .map_sg(). Adding the
default_iommu_map_sg() to rockchip iommu accordingly.

Signed-off-by: Simon Xue 
Signed-off-by: Shunqian Zheng 
Reviewed-by: Tomasz Figa 
---
 drivers/iommu/rockchip-iommu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index ec0ce62..3c16ec3 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1022,6 +1022,7 @@ static const struct iommu_ops rk_iommu_ops = {
.detach_dev = rk_iommu_detach_device,
.map = rk_iommu_map,
.unmap = rk_iommu_unmap,
+   .map_sg = default_iommu_map_sg,
.add_device = rk_iommu_add_device,
.remove_device = rk_iommu_remove_device,
.iova_to_phys = rk_iommu_iova_to_phys,
-- 
1.9.1



[PATCH v3 6/6] iommu/rockchip: enable rockchip iommu on ARM64 platform

2016-06-15 Thread Shunqian Zheng
From: Simon Xue 

This patch makes it possible to compile the rockchip-iommu driver on
ARM64 platform to be used with 64-bit SoCs equipped with this type
of IOMMU.

Signed-off-by: Simon Xue 
Signed-off-by: Shunqian Zheng 
Reviewed-by: Tomasz Figa 
---
 drivers/iommu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index ad08603..5572621 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -218,7 +218,7 @@ config OMAP_IOMMU_DEBUG
 
 config ROCKCHIP_IOMMU
bool "Rockchip IOMMU Support"
-   depends on ARM
+   depends on ARM || ARM64
depends on ARCH_ROCKCHIP || COMPILE_TEST
select IOMMU_API
select ARM_DMA_USE_IOMMU
-- 
1.9.1



[PATCH v3 4/6] drm: rockchip: use common iommu api to attach iommu

2016-06-15 Thread Shunqian Zheng
Rockchip DRM used the arm special API, arm_iommu_*(), to attach
iommu for ARM32 SoCs. This patch convert to common iommu API
so it would support ARM64 like RK3399.

The general idea is domain_alloc(), attach_device() and
arch_setup_dma_ops() to set dma_ops manually for DRM at the last.

Signed-off-by: Shunqian Zheng 
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 112 +---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 +
 2 files changed, 71 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index f5a68fc..b52c38d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -14,16 +14,16 @@
  * GNU General Public License for more details.
  */
 
-#include 
-
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_fb.h"
@@ -46,7 +46,8 @@ static bool is_support_iommu = true;
 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev)
 {
-   struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain *domain = private->domain;
int ret;
 
if (!is_support_iommu)
@@ -58,16 +59,25 @@ int rockchip_drm_dma_attach_device(struct drm_device 
*drm_dev,
 
dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
 
-   return arm_iommu_attach_device(dev, mapping);
+   ret = iommu_attach_device(domain, dev);
+   if (ret) {
+   dev_err(dev, "Failed to attach iommu device\n");
+   return ret;
+   }
+
+   /* TODO(djkurtz): fetch the mapping start/size from somewhere */
+   arch_setup_dma_ops(dev, 0x, SZ_2G, dev->bus->iommu_ops, false);
+   return 0;
 }
 
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev)
 {
-   if (!is_support_iommu)
-   return;
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain *domain = private->domain;
 
-   arm_iommu_detach_device(dev);
+   if (is_support_iommu)
+   iommu_detach_device(domain, dev);
 }
 
 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
@@ -132,10 +142,52 @@ static void rockchip_drm_crtc_disable_vblank(struct 
drm_device *dev,
priv->crtc_funcs[pipe]->disable_vblank(crtc);
 }
 
+static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct device *dev = drm_dev->dev;
+   int ret;
+
+   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
+ GFP_KERNEL);
+   if (!dev->dma_parms)
+   return -ENOMEM;
+
+   private->domain = iommu_domain_alloc(_bus_type);
+   if (!private->domain)
+   return -ENOMEM;
+
+   /* TODO(djkurtz): fetch the mapping start/size from somewhere */
+   ret = iommu_dma_init_domain(private->domain, 0x, SZ_2G);
+   if (ret) {
+   dev_err(dev, "Failed to init domain\n");
+   goto err_free_domain;
+   }
+
+   ret = rockchip_drm_dma_attach_device(drm_dev, dev);
+   if (ret) {
+   dev_err(dev, "Failed to attach device\n");
+   goto err_free_domain;
+   }
+
+   return 0;
+
+err_free_domain:
+   iommu_domain_free(private->domain);
+
+   return ret;
+}
+
+static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+
+   iommu_domain_free(private->domain);
+}
+
 static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
 {
struct rockchip_drm_private *private;
-   struct dma_iommu_mapping *mapping = NULL;
struct device *dev = drm_dev->dev;
struct drm_connector *connector;
int ret;
@@ -153,38 +205,18 @@ static int rockchip_drm_load(struct drm_device *drm_dev, 
unsigned long flags)
 
rockchip_drm_mode_config_init(drm_dev);
 
-   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
- GFP_KERNEL);
-   if (!dev->dma_parms) {
-   ret = -ENOMEM;
-   goto err_config_cleanup;
-   }
-
if (is_support_iommu) {
-   /* TODO(djkurtz): fetch the mapping start/size from somewhere */
-   mapping = arm_iommu_create_mapping(_bus_type,
-  0x,
-  SZ_2G);
-

[PATCH v3 0/6] fix bugs; enable iommu for ARM64

2016-06-15 Thread Shunqian Zheng
This series patches mainly for ARM64 supporting.
To do this, it first add virtual iommu slave device which DRM can attach to,
convert DRM driver to use common iommu API instead of the ARM32
functions, and then use DMA API in iommu driver to map, to flush cache.

Mainly changes of V3:
- Instead of registering virtual iommu in DTS, V3
  creates a iommu when attaching.
- Fix some bugs according to Tomasz's comments,
  most of them are offline, locally.

Shunqian Zheng (3):
  iommu/rockchip: support virtual iommu slave device
  drm: rockchip: use common iommu api to attach iommu
  iommu/rockchip: use DMA API to map, to flush cache

Simon Xue (3):
  iommu/rockchip: fix devm_{request,free}_irq parameter
  iommu/rockchip: add map_sg callback for rk_iommu_ops
  iommu/rockchip: enable rockchip iommu on ARM64 platform

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 112 -
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 +
 drivers/iommu/Kconfig   |   2 +-
 drivers/iommu/rockchip-iommu.c  | 251 ++--
 4 files changed, 273 insertions(+), 93 deletions(-)

-- 
1.9.1



[PATCH v2 5/7] drm: rockchip: use common iommu api to attach iommu

2016-06-08 Thread Shunqian Zheng
Rockchip DRM used the arm special API, arm_iommu_*(), to attach
iommu for ARM32 SoCs. This patch convert to common iommu API
so it would support ARM64 like RK3399.

The general idea is domain_alloc(), attach_device() and
arch_setup_dma_ops() to set dma_ops manually for DRM at the last.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 130 +++-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 +
 2 files changed, 89 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index f5a68fc..7965a66 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -14,8 +14,6 @@
  * GNU General Public License for more details.
  */
 
-#include 
-
 #include 
 #include 
 #include 
@@ -24,6 +22,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_fb.h"
@@ -46,7 +46,8 @@ static bool is_support_iommu = true;
 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev)
 {
-   struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain *domain = private->domain;
int ret;
 
if (!is_support_iommu)
@@ -58,16 +59,25 @@ int rockchip_drm_dma_attach_device(struct drm_device 
*drm_dev,
 
dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
 
-   return arm_iommu_attach_device(dev, mapping);
+   ret = iommu_attach_device(domain, dev);
+
+   if (ret) {
+   dev_err(dev, "Failed to attach iommu device\n");
+   return ret;
+   }
+   arch_setup_dma_ops(dev, 0x, SZ_2G,
+  (struct iommu_ops *)dev->bus->iommu_ops, false);
+   return 0;
 }
 
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev)
 {
-   if (!is_support_iommu)
-   return;
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain *domain = private->domain;
 
-   arm_iommu_detach_device(dev);
+   if (is_support_iommu)
+   iommu_detach_device(domain, dev);
 }
 
 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
@@ -132,10 +142,70 @@ static void rockchip_drm_crtc_disable_vblank(struct 
drm_device *dev,
priv->crtc_funcs[pipe]->disable_vblank(crtc);
 }
 
+static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct device *dev = drm_dev->dev;
+   int ret;
+
+   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
+ GFP_KERNEL);
+   if (!dev->dma_parms) {
+   ret = -ENOMEM;
+   return ret;
+   }
+
+   ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+   if (ret) {
+   dev_err(dev, "Failed to set coherent mask\n");
+   return ret;
+   }
+
+   dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+
+   private->domain = iommu_domain_alloc(_bus_type);
+   if (!private->domain)
+   return -ENOMEM;
+
+   ret = iommu_get_dma_cookie(private->domain);
+   if (ret) {
+   dev_err(dev, "Failed to get dma cookie\n");
+   goto err_free_domain;
+   }
+
+   ret = iommu_dma_init_domain(private->domain, 0x, SZ_2G);
+   if (ret) {
+   dev_err(dev, "Failed to init domain\n");
+   goto err_put_cookie;
+   }
+
+   ret = rockchip_drm_dma_attach_device(drm_dev, dev);
+   if (ret) {
+   dev_err(dev, "Failed to attach device\n");
+   goto err_put_cookie;
+   }
+
+   return 0;
+
+err_put_cookie:
+   iommu_put_dma_cookie(private->domain);
+err_free_domain:
+   iommu_domain_free(private->domain);
+
+   return ret;
+}
+
+static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+
+   iommu_put_dma_cookie(private->domain);
+   iommu_domain_free(private->domain);
+}
+
 static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
 {
struct rockchip_drm_private *private;
-   struct dma_iommu_mapping *mapping = NULL;
struct device *dev = drm_dev->dev;
struct drm_connector *connector;
int ret;
@@ -153,38 +223,18 @@ static int rockchip_drm_load(struct drm_device *drm_dev, 
unsigned long flags)
 
rockchip_drm_mode_config_init(drm_dev);
 
-   dev->dma_parms = devm_kzalloc(dev, size

[PATCH v2 5/7] drm: rockchip: use common iommu api to attach iommu

2016-06-08 Thread Shunqian Zheng
Rockchip DRM used the arm special API, arm_iommu_*(), to attach
iommu for ARM32 SoCs. This patch convert to common iommu API
so it would support ARM64 like RK3399.

The general idea is domain_alloc(), attach_device() and
arch_setup_dma_ops() to set dma_ops manually for DRM at the last.

Signed-off-by: Shunqian Zheng 
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 130 +++-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 +
 2 files changed, 89 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index f5a68fc..7965a66 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -14,8 +14,6 @@
  * GNU General Public License for more details.
  */
 
-#include 
-
 #include 
 #include 
 #include 
@@ -24,6 +22,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_fb.h"
@@ -46,7 +46,8 @@ static bool is_support_iommu = true;
 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev)
 {
-   struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain *domain = private->domain;
int ret;
 
if (!is_support_iommu)
@@ -58,16 +59,25 @@ int rockchip_drm_dma_attach_device(struct drm_device 
*drm_dev,
 
dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
 
-   return arm_iommu_attach_device(dev, mapping);
+   ret = iommu_attach_device(domain, dev);
+
+   if (ret) {
+   dev_err(dev, "Failed to attach iommu device\n");
+   return ret;
+   }
+   arch_setup_dma_ops(dev, 0x, SZ_2G,
+  (struct iommu_ops *)dev->bus->iommu_ops, false);
+   return 0;
 }
 
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev)
 {
-   if (!is_support_iommu)
-   return;
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain *domain = private->domain;
 
-   arm_iommu_detach_device(dev);
+   if (is_support_iommu)
+   iommu_detach_device(domain, dev);
 }
 
 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
@@ -132,10 +142,70 @@ static void rockchip_drm_crtc_disable_vblank(struct 
drm_device *dev,
priv->crtc_funcs[pipe]->disable_vblank(crtc);
 }
 
+static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct device *dev = drm_dev->dev;
+   int ret;
+
+   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
+ GFP_KERNEL);
+   if (!dev->dma_parms) {
+   ret = -ENOMEM;
+   return ret;
+   }
+
+   ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+   if (ret) {
+   dev_err(dev, "Failed to set coherent mask\n");
+   return ret;
+   }
+
+   dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+
+   private->domain = iommu_domain_alloc(_bus_type);
+   if (!private->domain)
+   return -ENOMEM;
+
+   ret = iommu_get_dma_cookie(private->domain);
+   if (ret) {
+   dev_err(dev, "Failed to get dma cookie\n");
+   goto err_free_domain;
+   }
+
+   ret = iommu_dma_init_domain(private->domain, 0x, SZ_2G);
+   if (ret) {
+   dev_err(dev, "Failed to init domain\n");
+   goto err_put_cookie;
+   }
+
+   ret = rockchip_drm_dma_attach_device(drm_dev, dev);
+   if (ret) {
+   dev_err(dev, "Failed to attach device\n");
+   goto err_put_cookie;
+   }
+
+   return 0;
+
+err_put_cookie:
+   iommu_put_dma_cookie(private->domain);
+err_free_domain:
+   iommu_domain_free(private->domain);
+
+   return ret;
+}
+
+static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+
+   iommu_put_dma_cookie(private->domain);
+   iommu_domain_free(private->domain);
+}
+
 static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
 {
struct rockchip_drm_private *private;
-   struct dma_iommu_mapping *mapping = NULL;
struct device *dev = drm_dev->dev;
struct drm_connector *connector;
int ret;
@@ -153,38 +223,18 @@ static int rockchip_drm_load(struct drm_device *drm_dev, 
unsigned long flags)
 
rockchip_drm_mode_config_init(drm_dev);
 
-   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
-

[PATCH v2 4/7] ARM: dts: rockchip: add virtual iommu for display

2016-06-08 Thread Shunqian Zheng
An virtual iommu without reg or interrupts for display.
Adding this according to iommu driver changes.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
---
 arch/arm/boot/dts/rk3288.dtsi | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 7fa932f..4cd535f 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -219,9 +219,15 @@
clock-names = "timer", "pclk";
};
 
+   display_mmu: virtual-iommu {
+   compatible = "rockchip,iommu";
+   #iommu-cells = <0>;
+   };
+
display-subsystem {
compatible = "rockchip,display-subsystem";
ports = <_out>, <_out>;
+   iommus = <_mmu>;
};
 
sdmmc: dwmmc@ff0c {
-- 
1.9.1



[PATCH v2 4/7] ARM: dts: rockchip: add virtual iommu for display

2016-06-08 Thread Shunqian Zheng
An virtual iommu without reg or interrupts for display.
Adding this according to iommu driver changes.

Signed-off-by: Shunqian Zheng 
---
 arch/arm/boot/dts/rk3288.dtsi | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 7fa932f..4cd535f 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -219,9 +219,15 @@
clock-names = "timer", "pclk";
};
 
+   display_mmu: virtual-iommu {
+   compatible = "rockchip,iommu";
+   #iommu-cells = <0>;
+   };
+
display-subsystem {
compatible = "rockchip,display-subsystem";
ports = <_out>, <_out>;
+   iommus = <_mmu>;
};
 
sdmmc: dwmmc@ff0c {
-- 
1.9.1



[PATCH v2 7/7] iommu/rockchip: enable rockchip iommu on ARM64 platform

2016-06-08 Thread Shunqian Zheng
From: Simon Xue <x...@rock-chips.com>

Signed-off-by: Simon Xue <x...@rock-chips.com>
Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
---
 drivers/iommu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index ad08603..5572621 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -218,7 +218,7 @@ config OMAP_IOMMU_DEBUG
 
 config ROCKCHIP_IOMMU
bool "Rockchip IOMMU Support"
-   depends on ARM
+   depends on ARM || ARM64
depends on ARCH_ROCKCHIP || COMPILE_TEST
select IOMMU_API
select ARM_DMA_USE_IOMMU
-- 
1.9.1



[PATCH v2 2/7] iommu/rockchip: add map_sg callback for rk_iommu_ops

2016-06-08 Thread Shunqian Zheng
From: Simon Xue <x...@rock-chips.com>

The iommu_dma_alloc() in iommu/dma-iommu.c calls iommu_map_sg()
that requires the callback iommu_ops .map_sg(). Adding the
default_iommu_map_sg() to rockchip iommu accordingly.

Signed-off-by: Simon Xue <x...@rock-chips.com>
Signed-off-by: Shunqian Zheng <x...@rock-chips.com>
---
 drivers/iommu/rockchip-iommu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index ec0ce62..3c16ec3 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1022,6 +1022,7 @@ static const struct iommu_ops rk_iommu_ops = {
.detach_dev = rk_iommu_detach_device,
.map = rk_iommu_map,
.unmap = rk_iommu_unmap,
+   .map_sg = default_iommu_map_sg,
.add_device = rk_iommu_add_device,
.remove_device = rk_iommu_remove_device,
.iova_to_phys = rk_iommu_iova_to_phys,
-- 
1.9.1



[PATCH v2 3/7] iommu/rockchip: support virtual iommu slave device

2016-06-08 Thread Shunqian Zheng
An virtual master device like DRM need to attach to iommu
domain to share the domain with VOP(the one with actual
iommu slave). We currently check the group is NULL to indicate
a virtual master, which is not true since we decide to use
the common iommu api to attach device in DRM.

With this patch, we can probe a virtual iommu device and
allow the DRM attaching to it. The virtual iommu is needed also
because we want convert to use DMA API for map/unmap, cache flush,
so that DRM buffer alloc still work even VOP is disabled.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
---
 drivers/iommu/rockchip-iommu.c | 37 +
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 3c16ec3..d6c3051 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -75,6 +75,11 @@
 
 #define IOMMU_REG_POLL_COUNT_FAST 1000
 
+/* A virtual iommu in device-tree registered without reg or
+ * interrupts, so the num_mmu is zero.
+ */
+#define RK_IOMMU_IS_VIRTUAL(iommu) (iommu->num_mmu == 0)
+
 struct rk_iommu_domain {
struct list_head iommus;
u32 *dt; /* page directory table */
@@ -789,13 +794,13 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
int ret, i;
phys_addr_t dte_addr;
 
-   /*
-* Allow 'virtual devices' (e.g., drm) to attach to domain.
-* Such a device does not belong to an iommu group.
-*/
iommu = rk_iommu_from_dev(dev);
-   if (!iommu)
+
+   iommu->domain = domain;
+   if (RK_IOMMU_IS_VIRTUAL(iommu)) {
+   dev_dbg(dev, "Attach virtual device to iommu domain\n");
return 0;
+   }
 
ret = rk_iommu_enable_stall(iommu);
if (ret)
@@ -805,7 +810,6 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
if (ret)
return ret;
 
-   iommu->domain = domain;
 
ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq,
   IRQF_SHARED, dev_name(dev), iommu);
@@ -842,10 +846,13 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
unsigned long flags;
int i;
 
-   /* Allow 'virtual devices' (eg drm) to detach from domain */
iommu = rk_iommu_from_dev(dev);
-   if (!iommu)
+
+   iommu->domain = NULL;
+   if (RK_IOMMU_IS_VIRTUAL(iommu)) {
+   dev_dbg(dev, "Master with virtual iommu detached from 
domain\n");
return;
+   }
 
spin_lock_irqsave(_domain->iommus_lock, flags);
list_del_init(>node);
@@ -862,8 +869,6 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
 
devm_free_irq(iommu->dev, iommu->irq, iommu);
 
-   iommu->domain = NULL;
-
dev_dbg(dev, "Detached from iommu domain\n");
 }
 
@@ -1034,6 +1039,7 @@ static int rk_iommu_probe(struct platform_device *pdev)
struct device *dev = >dev;
struct rk_iommu *iommu;
struct resource *res;
+   int num_res = pdev->num_resources;
int i;
 
iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
@@ -1043,12 +1049,19 @@ static int rk_iommu_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, iommu);
iommu->dev = dev;
iommu->num_mmu = 0;
-   iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * iommu->num_mmu,
+
+   if (!num_res) {
+   iommu->bases = NULL;
+   dev_info(dev, "this is a virtual iommu\n");
+   return 0;
+   }
+
+   iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * num_res,
GFP_KERNEL);
if (!iommu->bases)
return -ENOMEM;
 
-   for (i = 0; i < pdev->num_resources; i++) {
+   for (i = 0; i < num_res; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res)
continue;
-- 
1.9.1



[PATCH v2 7/7] iommu/rockchip: enable rockchip iommu on ARM64 platform

2016-06-08 Thread Shunqian Zheng
From: Simon Xue 

Signed-off-by: Simon Xue 
Signed-off-by: Shunqian Zheng 
---
 drivers/iommu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index ad08603..5572621 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -218,7 +218,7 @@ config OMAP_IOMMU_DEBUG
 
 config ROCKCHIP_IOMMU
bool "Rockchip IOMMU Support"
-   depends on ARM
+   depends on ARM || ARM64
depends on ARCH_ROCKCHIP || COMPILE_TEST
select IOMMU_API
select ARM_DMA_USE_IOMMU
-- 
1.9.1



[PATCH v2 2/7] iommu/rockchip: add map_sg callback for rk_iommu_ops

2016-06-08 Thread Shunqian Zheng
From: Simon Xue 

The iommu_dma_alloc() in iommu/dma-iommu.c calls iommu_map_sg()
that requires the callback iommu_ops .map_sg(). Adding the
default_iommu_map_sg() to rockchip iommu accordingly.

Signed-off-by: Simon Xue 
Signed-off-by: Shunqian Zheng 
---
 drivers/iommu/rockchip-iommu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index ec0ce62..3c16ec3 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1022,6 +1022,7 @@ static const struct iommu_ops rk_iommu_ops = {
.detach_dev = rk_iommu_detach_device,
.map = rk_iommu_map,
.unmap = rk_iommu_unmap,
+   .map_sg = default_iommu_map_sg,
.add_device = rk_iommu_add_device,
.remove_device = rk_iommu_remove_device,
.iova_to_phys = rk_iommu_iova_to_phys,
-- 
1.9.1



[PATCH v2 3/7] iommu/rockchip: support virtual iommu slave device

2016-06-08 Thread Shunqian Zheng
An virtual master device like DRM need to attach to iommu
domain to share the domain with VOP(the one with actual
iommu slave). We currently check the group is NULL to indicate
a virtual master, which is not true since we decide to use
the common iommu api to attach device in DRM.

With this patch, we can probe a virtual iommu device and
allow the DRM attaching to it. The virtual iommu is needed also
because we want convert to use DMA API for map/unmap, cache flush,
so that DRM buffer alloc still work even VOP is disabled.

Signed-off-by: Shunqian Zheng 
---
 drivers/iommu/rockchip-iommu.c | 37 +
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 3c16ec3..d6c3051 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -75,6 +75,11 @@
 
 #define IOMMU_REG_POLL_COUNT_FAST 1000
 
+/* A virtual iommu in device-tree registered without reg or
+ * interrupts, so the num_mmu is zero.
+ */
+#define RK_IOMMU_IS_VIRTUAL(iommu) (iommu->num_mmu == 0)
+
 struct rk_iommu_domain {
struct list_head iommus;
u32 *dt; /* page directory table */
@@ -789,13 +794,13 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
int ret, i;
phys_addr_t dte_addr;
 
-   /*
-* Allow 'virtual devices' (e.g., drm) to attach to domain.
-* Such a device does not belong to an iommu group.
-*/
iommu = rk_iommu_from_dev(dev);
-   if (!iommu)
+
+   iommu->domain = domain;
+   if (RK_IOMMU_IS_VIRTUAL(iommu)) {
+   dev_dbg(dev, "Attach virtual device to iommu domain\n");
return 0;
+   }
 
ret = rk_iommu_enable_stall(iommu);
if (ret)
@@ -805,7 +810,6 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
if (ret)
return ret;
 
-   iommu->domain = domain;
 
ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq,
   IRQF_SHARED, dev_name(dev), iommu);
@@ -842,10 +846,13 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
unsigned long flags;
int i;
 
-   /* Allow 'virtual devices' (eg drm) to detach from domain */
iommu = rk_iommu_from_dev(dev);
-   if (!iommu)
+
+   iommu->domain = NULL;
+   if (RK_IOMMU_IS_VIRTUAL(iommu)) {
+   dev_dbg(dev, "Master with virtual iommu detached from 
domain\n");
return;
+   }
 
spin_lock_irqsave(_domain->iommus_lock, flags);
list_del_init(>node);
@@ -862,8 +869,6 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
 
devm_free_irq(iommu->dev, iommu->irq, iommu);
 
-   iommu->domain = NULL;
-
dev_dbg(dev, "Detached from iommu domain\n");
 }
 
@@ -1034,6 +1039,7 @@ static int rk_iommu_probe(struct platform_device *pdev)
struct device *dev = >dev;
struct rk_iommu *iommu;
struct resource *res;
+   int num_res = pdev->num_resources;
int i;
 
iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
@@ -1043,12 +1049,19 @@ static int rk_iommu_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, iommu);
iommu->dev = dev;
iommu->num_mmu = 0;
-   iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * iommu->num_mmu,
+
+   if (!num_res) {
+   iommu->bases = NULL;
+   dev_info(dev, "this is a virtual iommu\n");
+   return 0;
+   }
+
+   iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * num_res,
GFP_KERNEL);
if (!iommu->bases)
return -ENOMEM;
 
-   for (i = 0; i < pdev->num_resources; i++) {
+   for (i = 0; i < num_res; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res)
continue;
-- 
1.9.1



[PATCH v2 6/7] iommu/rockchip: use DMA API to map, to flush cache

2016-06-08 Thread Shunqian Zheng
Use DMA API instead of architecture internal functions like
__cpuc_flush_dcache_area() etc.

To support the virtual device like DRM the virtual slave iommu
added in the previous patch, attaching to which the DRM can use
it own domain->dev for dma_map_*(), dma_sync_*() even VOP is disabled.

With this patch, this driver is available for ARM64 like RK3399.

Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
---
 drivers/iommu/rockchip-iommu.c | 113 ++---
 1 file changed, 71 insertions(+), 42 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index d6c3051..aafea6e 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -4,8 +4,6 @@
  * published by the Free Software Foundation.
  */
 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -61,8 +59,7 @@
 #define RK_MMU_IRQ_BUS_ERROR 0x02  /* bus read error */
 #define RK_MMU_IRQ_MASK  (RK_MMU_IRQ_PAGE_FAULT | RK_MMU_IRQ_BUS_ERROR)
 
-#define NUM_DT_ENTRIES 1024
-#define NUM_PT_ENTRIES 1024
+#define NUM_TLB_ENTRIES 1024 /* for both DT and PT */
 
 #define SPAGE_ORDER 12
 #define SPAGE_SIZE (1 << SPAGE_ORDER)
@@ -82,7 +79,9 @@
 
 struct rk_iommu_domain {
struct list_head iommus;
+   struct device *dev;
u32 *dt; /* page directory table */
+   dma_addr_t dt_dma;
spinlock_t iommus_lock; /* lock for iommus list */
spinlock_t dt_lock; /* lock for modifying page directory table */
 
@@ -98,14 +97,12 @@ struct rk_iommu {
struct iommu_domain *domain; /* domain to which iommu is attached */
 };
 
-static inline void rk_table_flush(u32 *va, unsigned int count)
+static inline void rk_table_flush(struct device *dev, dma_addr_t dma,
+ unsigned int count)
 {
-   phys_addr_t pa_start = virt_to_phys(va);
-   phys_addr_t pa_end = virt_to_phys(va + count);
-   size_t size = pa_end - pa_start;
+   size_t size = count * 4;
 
-   __cpuc_flush_dcache_area(va, size);
-   outer_flush_range(pa_start, pa_end);
+   dma_sync_single_range_for_device(dev, dma, 0, size, DMA_TO_DEVICE);
 }
 
 static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
@@ -188,10 +185,9 @@ static inline bool rk_dte_is_pt_valid(u32 dte)
return dte & RK_DTE_PT_VALID;
 }
 
-static u32 rk_mk_dte(u32 *pt)
+static inline u32 rk_mk_dte(dma_addr_t pt_dma)
 {
-   phys_addr_t pt_phys = virt_to_phys(pt);
-   return (pt_phys & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
+   return (pt_dma & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
 }
 
 /*
@@ -609,12 +605,14 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
  dma_addr_t iova)
 {
u32 *page_table, *dte_addr;
+   u32 dte_index = rk_iova_dte_index(iova);
u32 dte;
phys_addr_t pt_phys;
+   dma_addr_t pt_dma;
 
assert_spin_locked(_domain->dt_lock);
 
-   dte_addr = _domain->dt[rk_iova_dte_index(iova)];
+   dte_addr = _domain->dt[dte_index];
dte = *dte_addr;
if (rk_dte_is_pt_valid(dte))
goto done;
@@ -623,19 +621,27 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
if (!page_table)
return ERR_PTR(-ENOMEM);
 
-   dte = rk_mk_dte(page_table);
-   *dte_addr = dte;
+   pt_dma = dma_map_single(rk_domain->dev, page_table,
+   SPAGE_SIZE, DMA_TO_DEVICE);
+   if (dma_mapping_error(rk_domain->dev, pt_dma)) {
+   dev_err(rk_domain->dev, "dma mapping error\n");
+   free_page((unsigned long)page_table);
+   return ERR_PTR(-ENOMEM);
+   }
 
-   rk_table_flush(page_table, NUM_PT_ENTRIES);
-   rk_table_flush(dte_addr, 1);
+   dte = rk_mk_dte(pt_dma);
+   *dte_addr = dte;
 
+   rk_table_flush(rk_domain->dev, pt_dma, NUM_TLB_ENTRIES);
+   rk_table_flush(rk_domain->dev, rk_domain->dt_dma + dte_index * 4, 1);
 done:
pt_phys = rk_dte_pt_address(dte);
return (u32 *)phys_to_virt(pt_phys);
 }
 
 static size_t rk_iommu_unmap_iova(struct rk_iommu_domain *rk_domain,
- u32 *pte_addr, dma_addr_t iova, size_t size)
+ u32 *pte_addr, dma_addr_t pte_dma,
+ size_t size)
 {
unsigned int pte_count;
unsigned int pte_total = size / SPAGE_SIZE;
@@ -650,14 +656,14 @@ static size_t rk_iommu_unmap_iova(struct rk_iommu_domain 
*rk_domain,
pte_addr[pte_count] = rk_mk_pte_invalid(pte);
}
 
-   rk_table_flush(pte_addr, pte_count);
+   rk_table_flush(rk_domain->dev, pte_dma, pte_count);
 
return pte_count * SPAGE_SIZE;
 }
 
 static int rk_iommu_map_iova(struct rk_iommu_domain *rk_domain, u32 *pte_addr,
-dma_addr_t iova, ph

[PATCH v2 6/7] iommu/rockchip: use DMA API to map, to flush cache

2016-06-08 Thread Shunqian Zheng
Use DMA API instead of architecture internal functions like
__cpuc_flush_dcache_area() etc.

To support the virtual device like DRM the virtual slave iommu
added in the previous patch, attaching to which the DRM can use
it own domain->dev for dma_map_*(), dma_sync_*() even VOP is disabled.

With this patch, this driver is available for ARM64 like RK3399.

Signed-off-by: Shunqian Zheng 
---
 drivers/iommu/rockchip-iommu.c | 113 ++---
 1 file changed, 71 insertions(+), 42 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index d6c3051..aafea6e 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -4,8 +4,6 @@
  * published by the Free Software Foundation.
  */
 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -61,8 +59,7 @@
 #define RK_MMU_IRQ_BUS_ERROR 0x02  /* bus read error */
 #define RK_MMU_IRQ_MASK  (RK_MMU_IRQ_PAGE_FAULT | RK_MMU_IRQ_BUS_ERROR)
 
-#define NUM_DT_ENTRIES 1024
-#define NUM_PT_ENTRIES 1024
+#define NUM_TLB_ENTRIES 1024 /* for both DT and PT */
 
 #define SPAGE_ORDER 12
 #define SPAGE_SIZE (1 << SPAGE_ORDER)
@@ -82,7 +79,9 @@
 
 struct rk_iommu_domain {
struct list_head iommus;
+   struct device *dev;
u32 *dt; /* page directory table */
+   dma_addr_t dt_dma;
spinlock_t iommus_lock; /* lock for iommus list */
spinlock_t dt_lock; /* lock for modifying page directory table */
 
@@ -98,14 +97,12 @@ struct rk_iommu {
struct iommu_domain *domain; /* domain to which iommu is attached */
 };
 
-static inline void rk_table_flush(u32 *va, unsigned int count)
+static inline void rk_table_flush(struct device *dev, dma_addr_t dma,
+ unsigned int count)
 {
-   phys_addr_t pa_start = virt_to_phys(va);
-   phys_addr_t pa_end = virt_to_phys(va + count);
-   size_t size = pa_end - pa_start;
+   size_t size = count * 4;
 
-   __cpuc_flush_dcache_area(va, size);
-   outer_flush_range(pa_start, pa_end);
+   dma_sync_single_range_for_device(dev, dma, 0, size, DMA_TO_DEVICE);
 }
 
 static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
@@ -188,10 +185,9 @@ static inline bool rk_dte_is_pt_valid(u32 dte)
return dte & RK_DTE_PT_VALID;
 }
 
-static u32 rk_mk_dte(u32 *pt)
+static inline u32 rk_mk_dte(dma_addr_t pt_dma)
 {
-   phys_addr_t pt_phys = virt_to_phys(pt);
-   return (pt_phys & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
+   return (pt_dma & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
 }
 
 /*
@@ -609,12 +605,14 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
  dma_addr_t iova)
 {
u32 *page_table, *dte_addr;
+   u32 dte_index = rk_iova_dte_index(iova);
u32 dte;
phys_addr_t pt_phys;
+   dma_addr_t pt_dma;
 
assert_spin_locked(_domain->dt_lock);
 
-   dte_addr = _domain->dt[rk_iova_dte_index(iova)];
+   dte_addr = _domain->dt[dte_index];
dte = *dte_addr;
if (rk_dte_is_pt_valid(dte))
goto done;
@@ -623,19 +621,27 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
if (!page_table)
return ERR_PTR(-ENOMEM);
 
-   dte = rk_mk_dte(page_table);
-   *dte_addr = dte;
+   pt_dma = dma_map_single(rk_domain->dev, page_table,
+   SPAGE_SIZE, DMA_TO_DEVICE);
+   if (dma_mapping_error(rk_domain->dev, pt_dma)) {
+   dev_err(rk_domain->dev, "dma mapping error\n");
+   free_page((unsigned long)page_table);
+   return ERR_PTR(-ENOMEM);
+   }
 
-   rk_table_flush(page_table, NUM_PT_ENTRIES);
-   rk_table_flush(dte_addr, 1);
+   dte = rk_mk_dte(pt_dma);
+   *dte_addr = dte;
 
+   rk_table_flush(rk_domain->dev, pt_dma, NUM_TLB_ENTRIES);
+   rk_table_flush(rk_domain->dev, rk_domain->dt_dma + dte_index * 4, 1);
 done:
pt_phys = rk_dte_pt_address(dte);
return (u32 *)phys_to_virt(pt_phys);
 }
 
 static size_t rk_iommu_unmap_iova(struct rk_iommu_domain *rk_domain,
- u32 *pte_addr, dma_addr_t iova, size_t size)
+ u32 *pte_addr, dma_addr_t pte_dma,
+ size_t size)
 {
unsigned int pte_count;
unsigned int pte_total = size / SPAGE_SIZE;
@@ -650,14 +656,14 @@ static size_t rk_iommu_unmap_iova(struct rk_iommu_domain 
*rk_domain,
pte_addr[pte_count] = rk_mk_pte_invalid(pte);
}
 
-   rk_table_flush(pte_addr, pte_count);
+   rk_table_flush(rk_domain->dev, pte_dma, pte_count);
 
return pte_count * SPAGE_SIZE;
 }
 
 static int rk_iommu_map_iova(struct rk_iommu_domain *rk_domain, u32 *pte_addr,
-dma_addr_t iova, phys_add

[PATCH v2 1/7] iommu/rockchip: fix devm_{request,free}_irq parameter

2016-06-08 Thread Shunqian Zheng
From: Simon Xue <x...@rock-chips.com>

Even though the iommu shares irq with its master, using the *dev of iommu
instead of master's *dev for devm_{request,free}_irq makes things clear.

Signed-off-by: Simon Xue <x...@rock-chips.com>
Signed-off-by: Shunqian Zheng <zhen...@rock-chips.com>
---
 drivers/iommu/rockchip-iommu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index c7d6156..ec0ce62 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -807,7 +807,7 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
iommu->domain = domain;
 
-   ret = devm_request_irq(dev, iommu->irq, rk_iommu_irq,
+   ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq,
   IRQF_SHARED, dev_name(dev), iommu);
if (ret)
return ret;
@@ -860,7 +860,7 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
}
rk_iommu_disable_stall(iommu);
 
-   devm_free_irq(dev, iommu->irq, iommu);
+   devm_free_irq(iommu->dev, iommu->irq, iommu);
 
iommu->domain = NULL;
 
-- 
1.9.1



[PATCH v2 1/7] iommu/rockchip: fix devm_{request,free}_irq parameter

2016-06-08 Thread Shunqian Zheng
From: Simon Xue 

Even though the iommu shares irq with its master, using the *dev of iommu
instead of master's *dev for devm_{request,free}_irq makes things clear.

Signed-off-by: Simon Xue 
Signed-off-by: Shunqian Zheng 
---
 drivers/iommu/rockchip-iommu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index c7d6156..ec0ce62 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -807,7 +807,7 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
iommu->domain = domain;
 
-   ret = devm_request_irq(dev, iommu->irq, rk_iommu_irq,
+   ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq,
   IRQF_SHARED, dev_name(dev), iommu);
if (ret)
return ret;
@@ -860,7 +860,7 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
}
rk_iommu_disable_stall(iommu);
 
-   devm_free_irq(dev, iommu->irq, iommu);
+   devm_free_irq(iommu->dev, iommu->irq, iommu);
 
iommu->domain = NULL;
 
-- 
1.9.1



[PATCH v2 0/7] fix bugs; enable iommu for ARM64

2016-06-08 Thread Shunqian Zheng
This series patches mainly for ARM64 supporting.
To do this, it first add virtual iommu slave device which DRM can attach to,
convert DRM driver to use common iommu API instead of the ARM32
functions, and then use DMA API in iommu driver to map, to flush cache.

The v2 patches make a lot changes vs v1, so please forget the v1.

Shunqian Zheng (4):
  iommu/rockchip: support virtual iommu slave device
  ARM: dts: rockchip: add virtual iommu for display
  drm: rockchip: use common iommu api to attach iommu
  iommu/rockchip: use DMA API to map, to flush cache

Simon Xue (3):
  iommu/rockchip: fix devm_{request,free}_irq parameter
  iommu/rockchip: add map_sg callback for rk_iommu_ops
  iommu/rockchip: enable rockchip iommu on ARM64 platform

 arch/arm/boot/dts/rk3288.dtsi   |   6 ++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 130 
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 +
 drivers/iommu/Kconfig   |   2 +-
 drivers/iommu/rockchip-iommu.c  | 151 ++--
 5 files changed, 193 insertions(+), 97 deletions(-)

-- 
1.9.1



[PATCH v2 0/7] fix bugs; enable iommu for ARM64

2016-06-08 Thread Shunqian Zheng
This series patches mainly for ARM64 supporting.
To do this, it first add virtual iommu slave device which DRM can attach to,
convert DRM driver to use common iommu API instead of the ARM32
functions, and then use DMA API in iommu driver to map, to flush cache.

The v2 patches make a lot changes vs v1, so please forget the v1.

Shunqian Zheng (4):
  iommu/rockchip: support virtual iommu slave device
  ARM: dts: rockchip: add virtual iommu for display
  drm: rockchip: use common iommu api to attach iommu
  iommu/rockchip: use DMA API to map, to flush cache

Simon Xue (3):
  iommu/rockchip: fix devm_{request,free}_irq parameter
  iommu/rockchip: add map_sg callback for rk_iommu_ops
  iommu/rockchip: enable rockchip iommu on ARM64 platform

 arch/arm/boot/dts/rk3288.dtsi   |   6 ++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 130 
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 +
 drivers/iommu/Kconfig   |   2 +-
 drivers/iommu/rockchip-iommu.c  | 151 ++--
 5 files changed, 193 insertions(+), 97 deletions(-)

-- 
1.9.1



Re: [PATCH 4/5] iommu/rockchip: add ARM64 cache flush operation for iommu

2016-05-23 Thread Shunqian Zheng

Catalin, Robin,

On 2016年05月23日 21:35, Catalin Marinas wrote:

On Mon, May 23, 2016 at 11:44:14AM +0100, Robin Murphy wrote:

On 23/05/16 02:37, Shunqian Zheng wrote:

From: Simon <x...@rock-chips.com>

Signed-off-by: Simon <x...@rock-chips.com>
---
  drivers/iommu/rockchip-iommu.c | 4 
  1 file changed, 4 insertions(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 043d18c..1741b65 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -95,12 +95,16 @@ struct rk_iommu {

  static inline void rk_table_flush(u32 *va, unsigned int count)
  {
+#if defined(CONFIG_ARM)
phys_addr_t pa_start = virt_to_phys(va);
phys_addr_t pa_end = virt_to_phys(va + count);
size_t size = pa_end - pa_start;

__cpuc_flush_dcache_area(va, size);
outer_flush_range(pa_start, pa_end);
+#elif defined(CONFIG_ARM64)
+   __dma_flush_range(va, va + count);
+#endif

Ugh, please don't use arch-private cache maintenance functions directly from
a driver. Allocating/mapping page tables to be read by the IOMMU is still
DMA, so using the DMA APIs is the correct way to manage them, *especially*
if it needs to work across multiple architectures.
It's easier for us if changing  the __dma_flush_range() to 
__flush_dcache_area() is acceptable here?


Thank you,
- shunqian

I fully agree, these functions should not be used in drivers.





Re: [PATCH 4/5] iommu/rockchip: add ARM64 cache flush operation for iommu

2016-05-23 Thread Shunqian Zheng

Catalin, Robin,

On 2016年05月23日 21:35, Catalin Marinas wrote:

On Mon, May 23, 2016 at 11:44:14AM +0100, Robin Murphy wrote:

On 23/05/16 02:37, Shunqian Zheng wrote:

From: Simon 

Signed-off-by: Simon 
---
  drivers/iommu/rockchip-iommu.c | 4 
  1 file changed, 4 insertions(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 043d18c..1741b65 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -95,12 +95,16 @@ struct rk_iommu {

  static inline void rk_table_flush(u32 *va, unsigned int count)
  {
+#if defined(CONFIG_ARM)
phys_addr_t pa_start = virt_to_phys(va);
phys_addr_t pa_end = virt_to_phys(va + count);
size_t size = pa_end - pa_start;

__cpuc_flush_dcache_area(va, size);
outer_flush_range(pa_start, pa_end);
+#elif defined(CONFIG_ARM64)
+   __dma_flush_range(va, va + count);
+#endif

Ugh, please don't use arch-private cache maintenance functions directly from
a driver. Allocating/mapping page tables to be read by the IOMMU is still
DMA, so using the DMA APIs is the correct way to manage them, *especially*
if it needs to work across multiple architectures.
It's easier for us if changing  the __dma_flush_range() to 
__flush_dcache_area() is acceptable here?


Thank you,
- shunqian

I fully agree, these functions should not be used in drivers.





[PATCH 1/5] iommu/rockchip: fix devm_request_irq and devm_free_irq parameter

2016-05-22 Thread Shunqian Zheng
From: Simon 

When rk_iommu_attach_device or rk_iommu_detach_device be called, the second
parameter "dev" represent the device who own the iommu, so it is not resonable
using "dev" for devm_request_irq's first parameter. To avoid potential error,
we must use iommu device itself "iommu->dev" instead, the same as devm_free_irq.

Signed-off-by: Simon 
---
 drivers/iommu/rockchip-iommu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index c7d6156..ec0ce62 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -807,7 +807,7 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
iommu->domain = domain;
 
-   ret = devm_request_irq(dev, iommu->irq, rk_iommu_irq,
+   ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq,
   IRQF_SHARED, dev_name(dev), iommu);
if (ret)
return ret;
@@ -860,7 +860,7 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
}
rk_iommu_disable_stall(iommu);
 
-   devm_free_irq(dev, iommu->irq, iommu);
+   devm_free_irq(iommu->dev, iommu->irq, iommu);
 
iommu->domain = NULL;
 
-- 
1.9.1



[PATCH 3/5] iommu/rockchip: add sanity check for virtual device

2016-05-22 Thread Shunqian Zheng
From: Simon 

We mark DRM as "virtual" device by checking it's group,
which may no longer true with the new rockchip drm drv in
https://patchwork.kernel.org/patch/8876331/.

Checking the group->iommu_data for virtual device.

Signed-off-by: Simon 
---
 drivers/iommu/rockchip-iommu.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 3c16ec3..043d18c 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -764,6 +764,7 @@ static size_t rk_iommu_unmap(struct iommu_domain *domain, 
unsigned long _iova,
return unmap_size;
 }
 
+/* Return NULL for a virtual device like DRM */
 static struct rk_iommu *rk_iommu_from_dev(struct device *dev)
 {
struct iommu_group *group;
@@ -774,6 +775,11 @@ static struct rk_iommu *rk_iommu_from_dev(struct device 
*dev)
if (!group)
return NULL;
iommu_dev = iommu_group_get_iommudata(group);
+   if (!iommu_dev) {
+   dev_info(dev, "Possibly a virtual device\n");
+   return NULL;
+   }
+
rk_iommu = dev_get_drvdata(iommu_dev);
iommu_group_put(group);
 
@@ -791,7 +797,6 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
/*
 * Allow 'virtual devices' (e.g., drm) to attach to domain.
-* Such a device does not belong to an iommu group.
 */
iommu = rk_iommu_from_dev(dev);
if (!iommu)
-- 
1.9.1



[PATCH 1/5] iommu/rockchip: fix devm_request_irq and devm_free_irq parameter

2016-05-22 Thread Shunqian Zheng
From: Simon 

When rk_iommu_attach_device or rk_iommu_detach_device be called, the second
parameter "dev" represent the device who own the iommu, so it is not resonable
using "dev" for devm_request_irq's first parameter. To avoid potential error,
we must use iommu device itself "iommu->dev" instead, the same as devm_free_irq.

Signed-off-by: Simon 
---
 drivers/iommu/rockchip-iommu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index c7d6156..ec0ce62 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -807,7 +807,7 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
iommu->domain = domain;
 
-   ret = devm_request_irq(dev, iommu->irq, rk_iommu_irq,
+   ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq,
   IRQF_SHARED, dev_name(dev), iommu);
if (ret)
return ret;
@@ -860,7 +860,7 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
}
rk_iommu_disable_stall(iommu);
 
-   devm_free_irq(dev, iommu->irq, iommu);
+   devm_free_irq(iommu->dev, iommu->irq, iommu);
 
iommu->domain = NULL;
 
-- 
1.9.1



[PATCH 3/5] iommu/rockchip: add sanity check for virtual device

2016-05-22 Thread Shunqian Zheng
From: Simon 

We mark DRM as "virtual" device by checking it's group,
which may no longer true with the new rockchip drm drv in
https://patchwork.kernel.org/patch/8876331/.

Checking the group->iommu_data for virtual device.

Signed-off-by: Simon 
---
 drivers/iommu/rockchip-iommu.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 3c16ec3..043d18c 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -764,6 +764,7 @@ static size_t rk_iommu_unmap(struct iommu_domain *domain, 
unsigned long _iova,
return unmap_size;
 }
 
+/* Return NULL for a virtual device like DRM */
 static struct rk_iommu *rk_iommu_from_dev(struct device *dev)
 {
struct iommu_group *group;
@@ -774,6 +775,11 @@ static struct rk_iommu *rk_iommu_from_dev(struct device 
*dev)
if (!group)
return NULL;
iommu_dev = iommu_group_get_iommudata(group);
+   if (!iommu_dev) {
+   dev_info(dev, "Possibly a virtual device\n");
+   return NULL;
+   }
+
rk_iommu = dev_get_drvdata(iommu_dev);
iommu_group_put(group);
 
@@ -791,7 +797,6 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
/*
 * Allow 'virtual devices' (e.g., drm) to attach to domain.
-* Such a device does not belong to an iommu group.
 */
iommu = rk_iommu_from_dev(dev);
if (!iommu)
-- 
1.9.1



[PATCH 5/5] iommu/rockchip: enable rockchip iommu on ARM64 platform

2016-05-22 Thread Shunqian Zheng
From: Simon 

Signed-off-by: Simon 
---
 drivers/iommu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index ad08603..5572621 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -218,7 +218,7 @@ config OMAP_IOMMU_DEBUG
 
 config ROCKCHIP_IOMMU
bool "Rockchip IOMMU Support"
-   depends on ARM
+   depends on ARM || ARM64
depends on ARCH_ROCKCHIP || COMPILE_TEST
select IOMMU_API
select ARM_DMA_USE_IOMMU
-- 
1.9.1



[PATCH 5/5] iommu/rockchip: enable rockchip iommu on ARM64 platform

2016-05-22 Thread Shunqian Zheng
From: Simon 

Signed-off-by: Simon 
---
 drivers/iommu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index ad08603..5572621 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -218,7 +218,7 @@ config OMAP_IOMMU_DEBUG
 
 config ROCKCHIP_IOMMU
bool "Rockchip IOMMU Support"
-   depends on ARM
+   depends on ARM || ARM64
depends on ARCH_ROCKCHIP || COMPILE_TEST
select IOMMU_API
select ARM_DMA_USE_IOMMU
-- 
1.9.1



  1   2   >