All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-21  9:28 ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:28 UTC (permalink / raw)
  To: David Airlie, Mark Yao, Heiko Stuebner
  Cc: Joonyoung Shim, Kumar Gala, Ian Campbell, Rob Herring,
	Pawel Moll, Russell King, devicetree, linux-kernel, dri-devel,
	linux-rockchip, linux-arm-kernel, Yakir Yang


Hi, Mark and all.

This patch set would add the RGA direct rendering based 2d graphics
acceleration module.

This patch set is based on git repository below:
git://people.freedesktop.org/~airlied/linux drm-next
commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7

And the RGA driver is based on Exynos G2D driver, it only manages the
command lists received from user, so user should make the command list
to data and registers needed by operation to use.

I have prepared an userspace demo application for testing:
	https://github.com/yakir-Yang/libdrm-rockchip
That is a rockchip libdrm library, and I have write a simple test case
"rockchip_rga_test" that would test the below RGA features:
- solid
- copy
- rotation
- flip
- window clip
- dithering

Thanks,
- Yakir


Yakir Yang (4):
  drm: rockchip: add a common subdrv interfaces
  drm: rockchip: add RGA driver support
  ARM: dts: rockchip: add RGA device node for RK3288
  ARM: dst: rockchip: enable RGA support on veyron devices

 .../bindings/display/rockchip/rockchip-rga.txt     |  36 +
 arch/arm/boot/dts/rk3288-veyron.dtsi               |   4 +
 arch/arm/boot/dts/rk3288.dtsi                      |  13 +
 drivers/gpu/drm/rockchip/Kconfig                   |   9 +
 drivers/gpu/drm/rockchip/Makefile                  |   1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c        |  82 ++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h        |  19 +
 drivers/gpu/drm/rockchip/rockchip_drm_rga.c        | 977 +++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_rga.h        | 108 +++
 include/uapi/drm/rockchip_drm.h                    |  63 ++
 10 files changed, 1312 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.h
 create mode 100644 include/uapi/drm/rockchip_drm.h

-- 
1.9.1

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-21  9:28 ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:28 UTC (permalink / raw)
  To: David Airlie, Mark Yao, Heiko Stuebner
  Cc: Joonyoung Shim, Kumar Gala, Ian Campbell, Rob Herring,
	Pawel Moll, Russell King, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Yakir Yang


Hi, Mark and all.

This patch set would add the RGA direct rendering based 2d graphics
acceleration module.

This patch set is based on git repository below:
git://people.freedesktop.org/~airlied/linux drm-next
commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7

And the RGA driver is based on Exynos G2D driver, it only manages the
command lists received from user, so user should make the command list
to data and registers needed by operation to use.

I have prepared an userspace demo application for testing:
	https://github.com/yakir-Yang/libdrm-rockchip
That is a rockchip libdrm library, and I have write a simple test case
"rockchip_rga_test" that would test the below RGA features:
- solid
- copy
- rotation
- flip
- window clip
- dithering

Thanks,
- Yakir


Yakir Yang (4):
  drm: rockchip: add a common subdrv interfaces
  drm: rockchip: add RGA driver support
  ARM: dts: rockchip: add RGA device node for RK3288
  ARM: dst: rockchip: enable RGA support on veyron devices

 .../bindings/display/rockchip/rockchip-rga.txt     |  36 +
 arch/arm/boot/dts/rk3288-veyron.dtsi               |   4 +
 arch/arm/boot/dts/rk3288.dtsi                      |  13 +
 drivers/gpu/drm/rockchip/Kconfig                   |   9 +
 drivers/gpu/drm/rockchip/Makefile                  |   1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c        |  82 ++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h        |  19 +
 drivers/gpu/drm/rockchip/rockchip_drm_rga.c        | 977 +++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_rga.h        | 108 +++
 include/uapi/drm/rockchip_drm.h                    |  63 ++
 10 files changed, 1312 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.h
 create mode 100644 include/uapi/drm/rockchip_drm.h

-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-21  9:28 ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:28 UTC (permalink / raw)
  To: linux-arm-kernel


Hi, Mark and all.

This patch set would add the RGA direct rendering based 2d graphics
acceleration module.

This patch set is based on git repository below:
git://people.freedesktop.org/~airlied/linux drm-next
commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7

And the RGA driver is based on Exynos G2D driver, it only manages the
command lists received from user, so user should make the command list
to data and registers needed by operation to use.

I have prepared an userspace demo application for testing:
	https://github.com/yakir-Yang/libdrm-rockchip
That is a rockchip libdrm library, and I have write a simple test case
"rockchip_rga_test" that would test the below RGA features:
- solid
- copy
- rotation
- flip
- window clip
- dithering

Thanks,
- Yakir


Yakir Yang (4):
  drm: rockchip: add a common subdrv interfaces
  drm: rockchip: add RGA driver support
  ARM: dts: rockchip: add RGA device node for RK3288
  ARM: dst: rockchip: enable RGA support on veyron devices

 .../bindings/display/rockchip/rockchip-rga.txt     |  36 +
 arch/arm/boot/dts/rk3288-veyron.dtsi               |   4 +
 arch/arm/boot/dts/rk3288.dtsi                      |  13 +
 drivers/gpu/drm/rockchip/Kconfig                   |   9 +
 drivers/gpu/drm/rockchip/Makefile                  |   1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c        |  82 ++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h        |  19 +
 drivers/gpu/drm/rockchip/rockchip_drm_rga.c        | 977 +++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_rga.h        | 108 +++
 include/uapi/drm/rockchip_drm.h                    |  63 ++
 10 files changed, 1312 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.h
 create mode 100644 include/uapi/drm/rockchip_drm.h

-- 
1.9.1

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 1/4] drm: rockchip: add a common subdrv interfaces
  2016-03-21  9:28 ` Yakir Yang
  (?)
@ 2016-03-21  9:38   ` Yakir Yang
  -1 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:38 UTC (permalink / raw)
  To: David Airlie, Mark Yao, Heiko Stuebner
  Cc: Joonyoung Shim, Kumar Gala, Ian Campbell, Rob Herring,
	Pawel Moll, Russell King, devicetree, linux-kernel, dri-devel,
	linux-rockchip, linux-arm-kernel, Yakir Yang

Introduce a common subdrv register/unregister interfaces, help
external driver to hook the drm open/close event.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 49 +++++++++++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 15 +++++++++
 2 files changed, 64 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 896da09..4e0feb2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -36,6 +36,8 @@
 #define DRIVER_MAJOR	1
 #define DRIVER_MINOR	0
 
+static LIST_HEAD(rockchip_drm_subdrv_list);
+
 /*
  * Attach a (component) device to the shared drm dma mapping from master drm
  * device.  This is used by the VOPs to map GEM buffers to a common DMA
@@ -251,6 +253,51 @@ static int rockchip_drm_unload(struct drm_device *drm_dev)
 	return 0;
 }
 
+int rockchip_register_subdrv(struct drm_rockchip_subdrv *subdrv)
+{
+	if (!subdrv)
+		return -EINVAL;
+
+	list_add_tail(&subdrv->list, &rockchip_drm_subdrv_list);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rockchip_register_subdrv);
+
+int rockchip_unregister_subdrv(struct drm_rockchip_subdrv *subdrv)
+{
+	if (!subdrv)
+		return -EINVAL;
+
+	list_del(&subdrv->list);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rockchip_unregister_subdrv);
+
+static int rockchip_drm_open(struct drm_device *dev, struct drm_file *file)
+{
+	struct drm_rockchip_subdrv *subdrv;
+	int ret = 0;
+
+	list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list) {
+		ret = subdrv->open(dev, subdrv->dev, file);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void rockchip_drm_preclose(struct drm_device *dev,
+				  struct drm_file *file)
+{
+	struct drm_rockchip_subdrv *subdrv;
+
+	list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list)
+		subdrv->close(dev, subdrv->dev, file);
+}
+
 void rockchip_drm_lastclose(struct drm_device *dev)
 {
 	struct rockchip_drm_private *priv = dev->dev_private;
@@ -281,6 +328,8 @@ static struct drm_driver rockchip_drm_driver = {
 				  DRIVER_PRIME | DRIVER_ATOMIC,
 	.load			= rockchip_drm_load,
 	.unload			= rockchip_drm_unload,
+	.open			= rockchip_drm_open,
+	.preclose		= rockchip_drm_preclose,
 	.lastclose		= rockchip_drm_lastclose,
 	.get_vblank_counter	= drm_vblank_no_hw_counter,
 	.enable_vblank		= rockchip_drm_crtc_enable_vblank,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 3529f69..5ea5fcb 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -42,6 +42,17 @@ struct rockchip_crtc_funcs {
 	void (*wait_for_update)(struct drm_crtc *crtc);
 };
 
+struct drm_rockchip_subdrv {
+	struct list_head list;
+	struct device *dev;
+	struct drm_device *drm_dev;
+
+	int (*open)(struct drm_device *drm_dev, struct device *dev,
+		    struct drm_file *file);
+	void (*close)(struct drm_device *drm_dev, struct device *dev,
+		      struct drm_file *file);
+};
+
 struct rockchip_atomic_commit {
 	struct work_struct	work;
 	struct drm_atomic_state *state;
@@ -73,4 +84,8 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
 				   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
 				    struct device *dev);
+
+int rockchip_register_subdrv(struct drm_rockchip_subdrv *subdrv);
+int rockchip_unregister_subdrv(struct drm_rockchip_subdrv *subdrv);
+
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 1/4] drm: rockchip: add a common subdrv interfaces
@ 2016-03-21  9:38   ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:38 UTC (permalink / raw)
  To: David Airlie, Mark Yao, Heiko Stuebner
  Cc: devicetree, Russell King, Pawel Moll, Ian Campbell, linux-kernel,
	dri-devel, linux-rockchip, Rob Herring, Kumar Gala,
	linux-arm-kernel

Introduce a common subdrv register/unregister interfaces, help
external driver to hook the drm open/close event.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 49 +++++++++++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 15 +++++++++
 2 files changed, 64 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 896da09..4e0feb2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -36,6 +36,8 @@
 #define DRIVER_MAJOR	1
 #define DRIVER_MINOR	0
 
+static LIST_HEAD(rockchip_drm_subdrv_list);
+
 /*
  * Attach a (component) device to the shared drm dma mapping from master drm
  * device.  This is used by the VOPs to map GEM buffers to a common DMA
@@ -251,6 +253,51 @@ static int rockchip_drm_unload(struct drm_device *drm_dev)
 	return 0;
 }
 
+int rockchip_register_subdrv(struct drm_rockchip_subdrv *subdrv)
+{
+	if (!subdrv)
+		return -EINVAL;
+
+	list_add_tail(&subdrv->list, &rockchip_drm_subdrv_list);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rockchip_register_subdrv);
+
+int rockchip_unregister_subdrv(struct drm_rockchip_subdrv *subdrv)
+{
+	if (!subdrv)
+		return -EINVAL;
+
+	list_del(&subdrv->list);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rockchip_unregister_subdrv);
+
+static int rockchip_drm_open(struct drm_device *dev, struct drm_file *file)
+{
+	struct drm_rockchip_subdrv *subdrv;
+	int ret = 0;
+
+	list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list) {
+		ret = subdrv->open(dev, subdrv->dev, file);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void rockchip_drm_preclose(struct drm_device *dev,
+				  struct drm_file *file)
+{
+	struct drm_rockchip_subdrv *subdrv;
+
+	list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list)
+		subdrv->close(dev, subdrv->dev, file);
+}
+
 void rockchip_drm_lastclose(struct drm_device *dev)
 {
 	struct rockchip_drm_private *priv = dev->dev_private;
@@ -281,6 +328,8 @@ static struct drm_driver rockchip_drm_driver = {
 				  DRIVER_PRIME | DRIVER_ATOMIC,
 	.load			= rockchip_drm_load,
 	.unload			= rockchip_drm_unload,
+	.open			= rockchip_drm_open,
+	.preclose		= rockchip_drm_preclose,
 	.lastclose		= rockchip_drm_lastclose,
 	.get_vblank_counter	= drm_vblank_no_hw_counter,
 	.enable_vblank		= rockchip_drm_crtc_enable_vblank,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 3529f69..5ea5fcb 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -42,6 +42,17 @@ struct rockchip_crtc_funcs {
 	void (*wait_for_update)(struct drm_crtc *crtc);
 };
 
+struct drm_rockchip_subdrv {
+	struct list_head list;
+	struct device *dev;
+	struct drm_device *drm_dev;
+
+	int (*open)(struct drm_device *drm_dev, struct device *dev,
+		    struct drm_file *file);
+	void (*close)(struct drm_device *drm_dev, struct device *dev,
+		      struct drm_file *file);
+};
+
 struct rockchip_atomic_commit {
 	struct work_struct	work;
 	struct drm_atomic_state *state;
@@ -73,4 +84,8 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
 				   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
 				    struct device *dev);
+
+int rockchip_register_subdrv(struct drm_rockchip_subdrv *subdrv);
+int rockchip_unregister_subdrv(struct drm_rockchip_subdrv *subdrv);
+
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
-- 
1.9.1


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 1/4] drm: rockchip: add a common subdrv interfaces
@ 2016-03-21  9:38   ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:38 UTC (permalink / raw)
  To: linux-arm-kernel

Introduce a common subdrv register/unregister interfaces, help
external driver to hook the drm open/close event.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 49 +++++++++++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 15 +++++++++
 2 files changed, 64 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 896da09..4e0feb2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -36,6 +36,8 @@
 #define DRIVER_MAJOR	1
 #define DRIVER_MINOR	0
 
+static LIST_HEAD(rockchip_drm_subdrv_list);
+
 /*
  * Attach a (component) device to the shared drm dma mapping from master drm
  * device.  This is used by the VOPs to map GEM buffers to a common DMA
@@ -251,6 +253,51 @@ static int rockchip_drm_unload(struct drm_device *drm_dev)
 	return 0;
 }
 
+int rockchip_register_subdrv(struct drm_rockchip_subdrv *subdrv)
+{
+	if (!subdrv)
+		return -EINVAL;
+
+	list_add_tail(&subdrv->list, &rockchip_drm_subdrv_list);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rockchip_register_subdrv);
+
+int rockchip_unregister_subdrv(struct drm_rockchip_subdrv *subdrv)
+{
+	if (!subdrv)
+		return -EINVAL;
+
+	list_del(&subdrv->list);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rockchip_unregister_subdrv);
+
+static int rockchip_drm_open(struct drm_device *dev, struct drm_file *file)
+{
+	struct drm_rockchip_subdrv *subdrv;
+	int ret = 0;
+
+	list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list) {
+		ret = subdrv->open(dev, subdrv->dev, file);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void rockchip_drm_preclose(struct drm_device *dev,
+				  struct drm_file *file)
+{
+	struct drm_rockchip_subdrv *subdrv;
+
+	list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list)
+		subdrv->close(dev, subdrv->dev, file);
+}
+
 void rockchip_drm_lastclose(struct drm_device *dev)
 {
 	struct rockchip_drm_private *priv = dev->dev_private;
@@ -281,6 +328,8 @@ static struct drm_driver rockchip_drm_driver = {
 				  DRIVER_PRIME | DRIVER_ATOMIC,
 	.load			= rockchip_drm_load,
 	.unload			= rockchip_drm_unload,
+	.open			= rockchip_drm_open,
+	.preclose		= rockchip_drm_preclose,
 	.lastclose		= rockchip_drm_lastclose,
 	.get_vblank_counter	= drm_vblank_no_hw_counter,
 	.enable_vblank		= rockchip_drm_crtc_enable_vblank,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 3529f69..5ea5fcb 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -42,6 +42,17 @@ struct rockchip_crtc_funcs {
 	void (*wait_for_update)(struct drm_crtc *crtc);
 };
 
+struct drm_rockchip_subdrv {
+	struct list_head list;
+	struct device *dev;
+	struct drm_device *drm_dev;
+
+	int (*open)(struct drm_device *drm_dev, struct device *dev,
+		    struct drm_file *file);
+	void (*close)(struct drm_device *drm_dev, struct device *dev,
+		      struct drm_file *file);
+};
+
 struct rockchip_atomic_commit {
 	struct work_struct	work;
 	struct drm_atomic_state *state;
@@ -73,4 +84,8 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
 				   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
 				    struct device *dev);
+
+int rockchip_register_subdrv(struct drm_rockchip_subdrv *subdrv);
+int rockchip_unregister_subdrv(struct drm_rockchip_subdrv *subdrv);
+
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 2/4] drm: rockchip: add RGA driver support
  2016-03-21  9:28 ` Yakir Yang
  (?)
@ 2016-03-21  9:40   ` Yakir Yang
  -1 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:40 UTC (permalink / raw)
  To: David Airlie, Mark Yao, Heiko Stuebner
  Cc: Joonyoung Shim, Kumar Gala, Ian Campbell, Rob Herring,
	Pawel Moll, Russell King, devicetree, linux-kernel, dri-devel,
	linux-rockchip, linux-arm-kernel, Yakir Yang

Rockchip RGA is a separate 2D raster graphic acceleration unit. It
accelerates 2D graphics operations, such as point/line drawing, image
scaling, rotation, BitBLT, alpha blending and image blur/sharpness.

The RGA driver is based on Exynos G2D driver, it is performed by two
tasks simply.
1. Configures the rendering parameters, such as foreground color and
   coordinates data by setting the drawing context registers.
2. Start the rendering process by calling rga_exec() ioctl.

The RGA supports DMA mode as host interface. User can make command list
to reduce HOST(ARM) loads. The contents of The command list is setted to
relevant registers of RGA by DMA.

The command list is composed Header and command sets and Tail.
- Header: The number of command set(4Bytes)
- Command set: Register offset(4Bytes) + Register data(4Bytes)
- Tail: Pointer of base address of the other command list(4Bytes)

By Tail field, the G2D can process many command lists without halt at
one go.

The G2D has following the rendering pipeline.
               --->     Color Fill     --->
               |                          |
--> DMA (read) ---> Src Bitmap Process ----> Alpha/ROP ---> Format convert ---> DMA (Write)
               |                          |
               ---> Dst Bitmap Process --->

And supports various operations from the rendering pipeline.
- copy
- fast solid color fill
- rotation
- flip
- 4 operand raster operation(ROP4)
- alpha blending
- color key
- dithering
- etc

User should make the command list to data and registers needed by
operation to use. The Rockchip RGA driver only manages the command lists
received from user. Some registers needs memory base address(physical
address) of image. User doesn't know its physical address, so fills the
gem handle of that memory than address to command sets, then RGA driver
converts it to memory base address.

We adds three ioctls for Rockchip RGA.

- ioctls
DRM_ROCKCHIP_RGA_GET_VER: get the RGA hardware version
DRM_ROCKCHIP_RGA_SET_CMDLIST: set the command list from user to driver
DRM_ROCKCHIP_RGA_EXEC: execute the command lists setted to driver

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
 .../bindings/display/rockchip/rockchip-rga.txt     |  36 +
 drivers/gpu/drm/rockchip/Kconfig                   |   9 +
 drivers/gpu/drm/rockchip/Makefile                  |   1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c        |  35 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h        |   4 +
 drivers/gpu/drm/rockchip/rockchip_drm_rga.c        | 977 +++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_rga.h        | 108 +++
 include/uapi/drm/rockchip_drm.h                    |  63 ++
 8 files changed, 1232 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.h
 create mode 100644 include/uapi/drm/rockchip_drm.h

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
new file mode 100644
index 0000000..0c606cb
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
@@ -0,0 +1,36 @@
+device-tree bindings for rockchip 2D raster graphic acceleration controller (RGA)
+
+RGA is a separate 2D raster graphic acceleration unit. It accelerates 2D
+graphics operations, such as point/line drawing, image scaling, rotation,
+BitBLT, alpha blending and image blur/sharpness.
+
+Required properties:
+- compatible: value should be one of the following
+		"rockchip,rk3228-rga";
+		"rockchip,rk3288-rga";
+		"rockchip,rk3399-rga";
+
+- interrupts: RGA interrupt number.
+
+- clocks: phandle to RGA sclk/hclk/aclk clocks
+
+- clock-names: should be "aclk" "hclk" and "sclk"
+
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: should be "aclk" "hclk" and "sclk"
+
+Example:
+SoC specific DT entry:
+	rga: rga@ff680000 {
+		compatible = "rockchip,rk3399-rga";
+		reg = <0xff680000 0x10000>;
+		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "rga";
+		clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>;
+		clock-names = "aclk", "hclk", "sclk";
+
+		resets = <&cru SRST_A_RGA>, <&cru SRST_H_RGA>, <&cru SRST_RGA_CORE>;
+		reset-names = "aclk", "hclk", "sclk";
+		status = "disabled";
+	};
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 76b3362..220221b 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -16,6 +16,15 @@ config DRM_ROCKCHIP
 	  2D or 3D acceleration; acceleration is performed by other
 	  IP found on the SoC.
 
+config ROCKCHIP_DRM_RGA
+	tristate "Rockchip RGA support"
+	depends on DRM_ROCKCHIP
+	help
+	  Choose this option to enable support for Rockchip RGA.
+	  Rockchip RGA is a kind of hardware 2D accelerator, and it support
+	  solid roration, scaling, color format transform, say Y to enable its
+	  driver
+
 config ROCKCHIP_DW_HDMI
         tristate "Rockchip specific extensions for Synopsys DW HDMI"
         depends on DRM_ROCKCHIP
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index df8fbef..7de547c 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -9,5 +9,6 @@ rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
+obj-$(CONFIG_ROCKCHIP_DRM_RGA) += rockchip_drm_rga.o
 
 obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_vop_reg.o
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 4e0feb2..1638bc9 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -25,10 +25,13 @@
 #include <linux/of_graph.h>
 #include <linux/component.h>
 
+#include <drm/rockchip_drm.h>
+
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_fb.h"
 #include "rockchip_drm_fbdev.h"
 #include "rockchip_drm_gem.h"
+#include "rockchip_drm_rga.h"
 
 #define DRIVER_NAME	"rockchip"
 #define DRIVER_DESC	"RockChip Soc DRM"
@@ -277,16 +280,28 @@ EXPORT_SYMBOL_GPL(rockchip_unregister_subdrv);
 
 static int rockchip_drm_open(struct drm_device *dev, struct drm_file *file)
 {
+	struct rockchip_drm_file_private *file_priv;
 	struct drm_rockchip_subdrv *subdrv;
 	int ret = 0;
 
+	file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
+	if (!file_priv)
+		return -ENOMEM;
+
+	file->driver_priv = file_priv;
+
 	list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list) {
 		ret = subdrv->open(dev, subdrv->dev, file);
 		if (ret)
-			return ret;
+			goto err_file_priv_free;
 	}
 
 	return 0;
+
+err_file_priv_free:
+	kfree(file_priv);
+	file->driver_priv = NULL;
+	return ret;
 }
 
 static void rockchip_drm_preclose(struct drm_device *dev,
@@ -298,6 +313,12 @@ static void rockchip_drm_preclose(struct drm_device *dev,
 		subdrv->close(dev, subdrv->dev, file);
 }
 
+static void rockchip_drm_postclose(struct drm_device *dev,
+				   struct drm_file *file)
+{
+	kfree(file->driver_priv);
+}
+
 void rockchip_drm_lastclose(struct drm_device *dev)
 {
 	struct rockchip_drm_private *priv = dev->dev_private;
@@ -305,6 +326,15 @@ void rockchip_drm_lastclose(struct drm_device *dev)
 	drm_fb_helper_restore_fbdev_mode_unlocked(&priv->fbdev_helper);
 }
 
+static const struct drm_ioctl_desc rockchip_ioctls[] = {
+	DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_GET_VER, rockchip_rga_get_ver_ioctl,
+			  DRM_AUTH | DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_SET_CMDLIST, rockchip_rga_set_cmdlist_ioctl,
+			  DRM_AUTH | DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_EXEC, rockchip_rga_exec_ioctl,
+			  DRM_AUTH | DRM_RENDER_ALLOW),
+};
+
 static const struct file_operations rockchip_drm_driver_fops = {
 	.owner = THIS_MODULE,
 	.open = drm_open,
@@ -330,6 +360,7 @@ static struct drm_driver rockchip_drm_driver = {
 	.unload			= rockchip_drm_unload,
 	.open			= rockchip_drm_open,
 	.preclose		= rockchip_drm_preclose,
+	.postclose		= rockchip_drm_postclose,
 	.lastclose		= rockchip_drm_lastclose,
 	.get_vblank_counter	= drm_vblank_no_hw_counter,
 	.enable_vblank		= rockchip_drm_crtc_enable_vblank,
@@ -347,6 +378,8 @@ static struct drm_driver rockchip_drm_driver = {
 	.gem_prime_vmap		= rockchip_gem_prime_vmap,
 	.gem_prime_vunmap	= rockchip_gem_prime_vunmap,
 	.gem_prime_mmap		= rockchip_gem_mmap_buf,
+	.ioctls			= rockchip_ioctls,
+	.num_ioctls		= ARRAY_SIZE(rockchip_ioctls),
 	.fops			= &rockchip_drm_driver_fops,
 	.name	= DRIVER_NAME,
 	.desc	= DRIVER_DESC,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 5ea5fcb..ea30ba6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -53,6 +53,10 @@ struct drm_rockchip_subdrv {
 		      struct drm_file *file);
 };
 
+struct rockchip_drm_file_private {
+	struct rockchip_drm_rga_private *rga_priv;
+};
+
 struct rockchip_atomic_commit {
 	struct work_struct	work;
 	struct drm_atomic_state *state;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_rga.c b/drivers/gpu/drm/rockchip/rockchip_drm_rga.c
new file mode 100644
index 0000000..4202121
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_rga.c
@@ -0,0 +1,977 @@
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Yakir Yang <ykk@rock-chips.com>
+ *
+ * based on exynos_drm_g2d.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <drm/drmP.h>
+#include <drm/rockchip_drm.h>
+
+#include "rockchip_drm_drv.h"
+#include "rockchip_drm_rga.h"
+
+#define RGA_MODE_BASE_REG		0x0100
+#define RGA_MODE_MAX_REG		0x017C
+
+#define RGA_SYS_CTRL			0x0000
+#define RGA_CMD_CTRL			0x0004
+#define RGA_CMD_BASE			0x0008
+#define RGA_INT				0x0010
+#define RGA_MMU_CTRL0			0x0014
+#define RGA_VERSION_INFO		0x0028
+
+#define RGA_SRC_Y_RGB_BASE_ADDR		0x0108
+#define RGA_SRC_CB_BASE_ADDR		0x010C
+#define RGA_SRC_CR_BASE_ADDR		0x0110
+#define RGA_SRC1_RGB_BASE_ADDR		0x0114
+#define RGA_DST_Y_RGB_BASE_ADDR		0x013C
+#define RGA_DST_CB_BASE_ADDR		0x0140
+#define RGA_DST_CR_BASE_ADDR		0x014C
+#define RGA_MMU_CTRL1			0x016C
+#define RGA_MMU_SRC_BASE		0x0170
+#define RGA_MMU_SRC1_BASE		0x0174
+#define RGA_MMU_DST_BASE		0x0178
+
+static void rga_dma_flush_range(void *ptr, int size)
+{
+#ifdef CONFIG_ARM
+	dmac_flush_range(ptr, ptr + size);
+	outer_flush_range(virt_to_phys(ptr), virt_to_phys(ptr + size));
+#elif CONFIG_ARM64
+	__dma_flush_range(ptr, ptr + size);
+#endif
+}
+
+static inline void rga_write(struct rockchip_rga *rga, u32 reg, u32 value)
+{
+	writel(value, rga->regs + reg);
+}
+
+static inline u32 rga_read(struct rockchip_rga *rga, u32 reg)
+{
+	return readl(rga->regs + reg);
+}
+
+static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
+{
+	u32 temp = rga_read(rga, reg) & ~(mask);
+
+	temp |= val & mask;
+	rga_write(rga, reg, temp);
+}
+
+static int rga_enable_clocks(struct rockchip_rga *rga)
+{
+	int ret;
+
+	ret = clk_prepare_enable(rga->sclk);
+	if (ret) {
+		dev_err(rga->dev, "Cannot enable rga sclk: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(rga->aclk);
+	if (ret) {
+		dev_err(rga->dev, "Cannot enable rga aclk: %d\n", ret);
+		goto err_disable_sclk;
+	}
+
+	ret = clk_prepare_enable(rga->hclk);
+	if (ret) {
+		dev_err(rga->dev, "Cannot enable rga hclk: %d\n", ret);
+		goto err_disable_aclk;
+	}
+
+	return 0;
+
+err_disable_sclk:
+	clk_disable_unprepare(rga->sclk);
+err_disable_aclk:
+	clk_disable_unprepare(rga->aclk);
+
+	return ret;
+}
+
+static void rga_disable_clocks(struct rockchip_rga *rga)
+{
+	clk_disable_unprepare(rga->sclk);
+	clk_disable_unprepare(rga->hclk);
+	clk_disable_unprepare(rga->aclk);
+}
+
+static void rga_init_cmdlist(struct rockchip_rga *rga)
+{
+	struct rga_cmdlist_node *node;
+	int nr;
+
+	node = rga->cmdlist_node;
+
+	for (nr = 0; nr < ARRAY_SIZE(rga->cmdlist_node); nr++)
+		list_add_tail(&node[nr].list, &rga->free_cmdlist);
+}
+
+static int rga_alloc_dma_buf_for_cmdlist(struct rga_runqueue_node *runqueue)
+{
+	struct list_head *run_cmdlist = &runqueue->run_cmdlist;
+	struct device *dev = runqueue->dev;
+	struct dma_attrs cmdlist_dma_attrs;
+	struct rga_cmdlist_node *node;
+	void *cmdlist_pool_virt;
+	dma_addr_t cmdlist_pool;
+	int cmdlist_cnt = 0;
+	int count = 0;
+
+	list_for_each_entry(node, run_cmdlist, list)
+		cmdlist_cnt++;
+
+	init_dma_attrs(&cmdlist_dma_attrs);
+	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &runqueue->cmdlist_dma_attrs);
+
+	cmdlist_pool_virt = dma_alloc_attrs(dev, cmdlist_cnt * RGA_CMDLIST_SIZE,
+					    &cmdlist_pool, GFP_KERNEL,
+					    &cmdlist_dma_attrs);
+	if (!cmdlist_pool_virt) {
+		dev_err(dev, "failed to allocate cmdlist dma memory\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * Fill in the RGA operation registers from cmdlist command buffer,
+	 * and also filled in the MMU TLB base information.
+	 */
+	list_for_each_entry(node, run_cmdlist, list) {
+		struct rga_cmdlist *cmdlist = &node->cmdlist;
+		unsigned int mmu_ctrl = 0;
+		unsigned int *dest;
+		unsigned int reg;
+		int i;
+
+		dest = cmdlist_pool_virt + RGA_CMDLIST_SIZE * 4 * count++;
+
+		for (i = 0; i < cmdlist->last / 2; i++) {
+			reg = (node->cmdlist.data[2 * i] - RGA_MODE_BASE_REG);
+			if (reg > RGA_MODE_BASE_REG)
+				continue;
+			dest[reg << 2] = cmdlist->data[2 * i + 1];
+		}
+
+		if (cmdlist->src_mmu_pages) {
+			reg = RGA_MMU_SRC_BASE - RGA_MODE_BASE_REG;
+			dest[reg << 2] = virt_to_phys(cmdlist->src_mmu_pages) >> 4;
+			mmu_ctrl |= 0x7;
+		}
+
+		if (cmdlist->dst_mmu_pages) {
+			reg = RGA_MMU_DST_BASE - RGA_MODE_BASE_REG;
+			dest[reg << 2] = virt_to_phys(cmdlist->dst_mmu_pages) >> 4;
+			mmu_ctrl |= 0x7 << 8;
+		}
+
+		if (cmdlist->src1_mmu_pages) {
+			reg = RGA_MMU_SRC1_BASE - RGA_MODE_BASE_REG;
+			dest[reg << 2] = virt_to_phys(cmdlist->src1_mmu_pages) >> 4;
+			mmu_ctrl |= 0x7 << 4;
+		}
+
+		reg = RGA_MMU_CTRL1 - RGA_MODE_BASE_REG;
+		dest[reg << 2] = mmu_ctrl;
+	}
+
+	rga_dma_flush_range(cmdlist_pool_virt, cmdlist_cnt * RGA_CMDLIST_SIZE);
+
+	runqueue->cmdlist_dma_attrs = cmdlist_dma_attrs;
+	runqueue->cmdlist_pool_virt = cmdlist_pool_virt;
+	runqueue->cmdlist_pool = cmdlist_pool;
+	runqueue->cmdlist_cnt = cmdlist_cnt;
+
+	return 0;
+}
+
+static int rga_check_reg_offset(struct device *dev,
+				struct rga_cmdlist_node *node)
+{
+	struct rga_cmdlist *cmdlist = &node->cmdlist;
+	int index;
+	int reg;
+	int i;
+
+	for (i = 0; i < cmdlist->last / 2; i++) {
+		index = cmdlist->last - 2 * (i + 1);
+		reg = cmdlist->data[index];
+
+		switch (reg) {
+		case RGA_BUF_TYPE_GEMFD | RGA_DST_Y_RGB_BASE_ADDR:
+		case RGA_BUF_TYPE_GEMFD | RGA_SRC_Y_RGB_BASE_ADDR:
+			break;
+
+		case RGA_BUF_TYPE_USERPTR | RGA_DST_Y_RGB_BASE_ADDR:
+		case RGA_BUF_TYPE_USERPTR | RGA_SRC_Y_RGB_BASE_ADDR:
+			goto err;
+
+		default:
+			if (reg < RGA_MODE_BASE_REG || reg > RGA_MODE_MAX_REG)
+				goto err;
+
+			if (reg % 4)
+				goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	dev_err(dev, "Bad register offset: 0x%lx\n", cmdlist->data[index]);
+	return -EINVAL;
+}
+
+static struct dma_buf_attachment *
+rga_gem_buf_to_pages(struct rockchip_rga *rga, void **mmu_pages, int fd)
+{
+	struct dma_buf_attachment *attach;
+	struct dma_buf *dmabuf;
+	struct sg_table *sgt;
+	struct scatterlist *sgl;
+	unsigned int mapped_size = 0;
+	unsigned int address;
+	unsigned int len;
+	unsigned int i, p;
+	unsigned int *pages;
+	int ret;
+
+	dmabuf = dma_buf_get(fd);
+	if (IS_ERR(dmabuf)) {
+		dev_err(rga->dev, "Failed to get dma_buf with fd %d\n", fd);
+		return ERR_PTR(-EINVAL);
+	}
+
+	attach = dma_buf_attach(dmabuf, rga->dev);
+	if (IS_ERR(attach)) {
+		dev_err(rga->dev, "Failed to attach dma_buf\n");
+		ret = PTR_ERR(attach);
+		goto failed_attach;
+	}
+
+	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+	if (IS_ERR(sgt)) {
+		dev_err(rga->dev, "Failed to map dma_buf attachment\n");
+		ret = PTR_ERR(sgt);
+		goto failed_detach;
+	}
+
+	/*
+	 * Alloc (2^3 * 4K) = 32K byte for storing pages, those space could
+	 * cover 32K * 4K = 128M ram address.
+	 */
+	pages = (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
+
+	for_each_sg(sgt->sgl, sgl, sgt->nents, i) {
+		len = sg_dma_len(sgl) >> PAGE_SHIFT;
+		address = sg_phys(sgl);
+
+		for (p = 0; p < len; p++) {
+			dma_addr_t phys = address + (p << PAGE_SHIFT);
+			void *virt = phys_to_virt(phys);
+
+			rga_dma_flush_range(virt, 4 * 1024);
+			pages[mapped_size + p] = phys;
+		}
+
+		mapped_size += len;
+	}
+
+	rga_dma_flush_range(pages, 32 * 1024);
+
+	*mmu_pages = pages;
+
+	dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+
+	return attach;
+
+failed_detach:
+	dma_buf_detach(dmabuf, attach);
+failed_attach:
+	dma_buf_put(dmabuf);
+
+	return ERR_PTR(ret);
+}
+
+static int rga_map_cmdlist_gem(struct rockchip_rga *rga,
+			       struct rga_cmdlist_node *node,
+			       struct drm_device *drm_dev,
+			       struct drm_file *file)
+{
+	struct rga_cmdlist *cmdlist = &node->cmdlist;
+	struct dma_buf_attachment *attach;
+	void *mmu_pages;
+	int fd;
+	int i;
+
+	for (i = 0; i < cmdlist->last / 2; i++) {
+		int index = cmdlist->last - 2 * (i + 1);
+
+		switch (cmdlist->data[index]) {
+		case RGA_SRC_Y_RGB_BASE_ADDR | RGA_BUF_TYPE_GEMFD:
+			fd = cmdlist->data[index + 1];
+			attach = rga_gem_buf_to_pages(rga, &mmu_pages, fd);
+
+			cmdlist->src_attach = attach;
+			cmdlist->src_mmu_pages = mmu_pages;
+			break;
+
+		case RGA_DST_Y_RGB_BASE_ADDR | RGA_BUF_TYPE_GEMFD:
+			fd = cmdlist->data[index + 1];
+			attach = rga_gem_buf_to_pages(rga, &mmu_pages, fd);
+
+			cmdlist->dst_attach = attach;
+			cmdlist->dst_mmu_pages = mmu_pages;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static void rga_unmap_cmdlist_gem(struct rockchip_rga *rga,
+				  struct rga_cmdlist_node *node)
+{
+	struct dma_buf_attachment *attach;
+	struct dma_buf *dma_buf;
+
+	attach = node->cmdlist.src_attach;
+	if (attach) {
+		dma_buf = attach->dmabuf;
+		dma_buf_detach(dma_buf, attach);
+		dma_buf_put(dma_buf);
+	}
+	node->cmdlist.src_attach = NULL;
+
+	attach = node->cmdlist.dst_attach;
+	if (attach) {
+		dma_buf = attach->dmabuf;
+		dma_buf_detach(dma_buf, attach);
+		dma_buf_put(dma_buf);
+	}
+	node->cmdlist.dst_attach = NULL;
+
+	if (node->cmdlist.src_mmu_pages)
+		free_pages((unsigned long)node->cmdlist.src_mmu_pages, 3);
+	node->cmdlist.src_mmu_pages = NULL;
+
+	if (node->cmdlist.src1_mmu_pages)
+		free_pages((unsigned long)node->cmdlist.src1_mmu_pages, 3);
+	node->cmdlist.src1_mmu_pages = NULL;
+
+	if (node->cmdlist.dst_mmu_pages)
+		free_pages((unsigned long)node->cmdlist.dst_mmu_pages, 3);
+	node->cmdlist.dst_mmu_pages = NULL;
+}
+
+static void rga_cmd_start(struct rockchip_rga *rga,
+			  struct rga_runqueue_node *runqueue)
+{
+	int ret;
+
+	ret = pm_runtime_get_sync(rga->dev);
+	if (ret < 0)
+		return;
+
+	rga_write(rga, RGA_SYS_CTRL, 0x00);
+
+	rga_write(rga, RGA_CMD_BASE, runqueue->cmdlist_pool);
+
+	rga_write(rga, RGA_SYS_CTRL, 0x22);
+
+	rga_write(rga, RGA_INT, 0x600);
+
+	rga_write(rga, RGA_CMD_CTRL, ((runqueue->cmdlist_cnt - 1) << 3) | 0x1);
+}
+
+static void rga_free_runqueue_node(struct rockchip_rga *rga,
+				   struct rga_runqueue_node *runqueue)
+{
+	struct rga_cmdlist_node *node;
+
+	if (!runqueue)
+		return;
+
+	if (runqueue->cmdlist_pool_virt && runqueue->cmdlist_pool)
+		dma_free_attrs(rga->dev, runqueue->cmdlist_cnt * RGA_CMDLIST_SIZE,
+			       runqueue->cmdlist_pool_virt,
+			       runqueue->cmdlist_pool,
+			       &runqueue->cmdlist_dma_attrs);
+
+	mutex_lock(&rga->cmdlist_mutex);
+	/*
+	 * commands in run_cmdlist have been completed so unmap all gem
+	 * objects in each command node so that they are unreferenced.
+	 */
+	list_for_each_entry(node, &runqueue->run_cmdlist, list)
+		rga_unmap_cmdlist_gem(rga, node);
+	list_splice_tail_init(&runqueue->run_cmdlist, &rga->free_cmdlist);
+	mutex_unlock(&rga->cmdlist_mutex);
+
+	kmem_cache_free(rga->runqueue_slab, runqueue);
+}
+
+static struct rga_runqueue_node *rga_get_runqueue(struct rockchip_rga *rga)
+{
+	struct rga_runqueue_node *runqueue;
+
+	if (list_empty(&rga->runqueue_list))
+		return NULL;
+
+	runqueue = list_first_entry(&rga->runqueue_list,
+				    struct rga_runqueue_node, list);
+	list_del_init(&runqueue->list);
+
+	return runqueue;
+}
+
+static void rga_exec_runqueue(struct rockchip_rga *rga)
+{
+	rga->runqueue_node = rga_get_runqueue(rga);
+	if (rga->runqueue_node)
+		rga_cmd_start(rga, rga->runqueue_node);
+}
+
+static struct rga_cmdlist_node *rga_get_cmdlist(struct rockchip_rga *rga)
+{
+	struct rga_cmdlist_node *node;
+	struct device *dev = rga->dev;
+
+	mutex_lock(&rga->cmdlist_mutex);
+	if (list_empty(&rga->free_cmdlist)) {
+		dev_err(dev, "there is no free cmdlist\n");
+		mutex_unlock(&rga->cmdlist_mutex);
+		return NULL;
+	}
+
+	node = list_first_entry(&rga->free_cmdlist,
+				struct rga_cmdlist_node, list);
+	list_del_init(&node->list);
+	mutex_unlock(&rga->cmdlist_mutex);
+
+	return node;
+}
+
+static void rga_add_cmdlist_to_inuse(struct rockchip_drm_rga_private *rga_priv,
+				     struct rga_cmdlist_node *node)
+{
+	struct rga_cmdlist_node *lnode;
+
+	if (list_empty(&rga_priv->inuse_cmdlist))
+		goto add_to_list;
+
+	/* this links to base address of new cmdlist */
+	lnode = list_entry(rga_priv->inuse_cmdlist.prev,
+			   struct rga_cmdlist_node, list);
+
+add_to_list:
+	list_add_tail(&node->list, &rga_priv->inuse_cmdlist);
+}
+
+/*
+ * IOCRL functions for userspace to get RGA version.
+ */
+int rockchip_rga_get_ver_ioctl(struct drm_device *drm_dev, void *data,
+			       struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
+	struct drm_rockchip_rga_get_ver *ver = data;
+	struct rockchip_rga *rga;
+	struct device *dev;
+
+	if (!rga_priv)
+		return -ENODEV;
+
+	dev = rga_priv->dev;
+	if (!dev)
+		return -ENODEV;
+
+	rga = dev_get_drvdata(dev);
+	if (!rga)
+		return -EFAULT;
+
+	ver->major = rga->version.major;
+	ver->minor = rga->version.minor;
+
+	return 0;
+}
+
+/*
+ * IOCRL functions for userspace to send an RGA request.
+ */
+int rockchip_rga_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
+				   struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
+	struct drm_rockchip_rga_set_cmdlist *req = data;
+	struct rga_cmdlist_node *node;
+	struct rga_cmdlist *cmdlist;
+	struct rockchip_rga *rga;
+	int ret;
+
+	if (!rga_priv)
+		return -ENODEV;
+
+	if (!rga_priv->dev)
+		return -ENODEV;
+
+	rga = dev_get_drvdata(rga_priv->dev);
+	if (!rga)
+		return -EFAULT;
+
+	node = rga_get_cmdlist(rga);
+	if (!node)
+		return -ENOMEM;
+
+	cmdlist = &node->cmdlist;
+	cmdlist->last = 0;
+
+	if (req->cmd_nr > RGA_CMDLIST_SIZE || req->cmd_buf_nr > RGA_CMDBUF_SIZE) {
+		dev_err(rga->dev, "cmdlist size is too big\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Copy the command / buffer registers setting from userspace, each
+	 * command have two integer, one for register offset, another for
+	 * register value.
+	 */
+	if (copy_from_user((void *)cmdlist->data, (const void __user *)req->cmd,
+			   sizeof(struct drm_rockchip_rga_cmd) * req->cmd_nr))
+		return -EFAULT;
+	cmdlist->last += req->cmd_nr * 2;
+
+	if (copy_from_user((void *)cmdlist->data + cmdlist->last,
+			   (const void __user *)req->cmd_buf,
+			   sizeof(struct drm_rockchip_rga_cmd) * req->cmd_buf_nr))
+		return -EFAULT;
+	cmdlist->last += req->cmd_buf_nr * 2;
+
+	/*
+	 * Check the userspace command registers, and mapping the framebuffer,
+	 * create the RGA mmu pages or get the framebuffer dma address.
+	 */
+	ret = rga_check_reg_offset(rga->dev, node);
+	if (ret < 0)
+		return ret;
+
+	ret = rga_map_cmdlist_gem(rga, node, drm_dev, file);
+	if (ret < 0)
+		return ret;
+
+	rga_add_cmdlist_to_inuse(rga_priv, node);
+
+	return 0;
+}
+
+/*
+ * IOCRL functions for userspace to start RGA transform.
+ */
+int rockchip_rga_exec_ioctl(struct drm_device *drm_dev, void *data,
+			    struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
+	struct rga_runqueue_node *runqueue;
+	struct rockchip_rga *rga;
+	struct device *dev;
+	int ret;
+
+	if (!rga_priv)
+		return -ENODEV;
+
+	dev = rga_priv->dev;
+	if (!dev)
+		return -ENODEV;
+
+	rga = dev_get_drvdata(dev);
+	if (!rga)
+		return -EFAULT;
+
+	runqueue = kmem_cache_alloc(rga->runqueue_slab, GFP_KERNEL);
+	if (!runqueue) {
+		dev_err(rga->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	runqueue->dev = rga->dev;
+
+	init_completion(&runqueue->complete);
+
+	INIT_LIST_HEAD(&runqueue->run_cmdlist);
+
+	list_splice_init(&rga_priv->inuse_cmdlist, &runqueue->run_cmdlist);
+
+	if (list_empty(&runqueue->run_cmdlist)) {
+		dev_err(rga->dev, "there is no inuse cmdlist\n");
+		kmem_cache_free(rga->runqueue_slab, runqueue);
+		return -EPERM;
+	}
+
+	ret = rga_alloc_dma_buf_for_cmdlist(runqueue);
+	if (ret < 0) {
+		dev_err(rga->dev, "cmdlist init failed\n");
+		return ret;
+	}
+
+	mutex_lock(&rga->runqueue_mutex);
+	runqueue->pid = current->pid;
+	runqueue->file = file;
+	list_add_tail(&runqueue->list, &rga->runqueue_list);
+	if (!rga->runqueue_node)
+		rga_exec_runqueue(rga);
+	mutex_unlock(&rga->runqueue_mutex);
+
+	wait_for_completion(&runqueue->complete);
+	rga_free_runqueue_node(rga, runqueue);
+
+	return 0;
+}
+
+static int rockchip_rga_open(struct drm_device *drm_dev, struct device *dev,
+			     struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv;
+
+	rga_priv = kzalloc(sizeof(*rga_priv), GFP_KERNEL);
+	if (!rga_priv)
+		return -ENOMEM;
+
+	rga_priv->dev = dev;
+	file_priv->rga_priv = rga_priv;
+
+	INIT_LIST_HEAD(&rga_priv->inuse_cmdlist);
+
+	return 0;
+}
+
+static void rockchip_rga_close(struct drm_device *drm_dev, struct device *dev,
+			       struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
+	struct rga_cmdlist_node *node, *n;
+	struct rockchip_rga *rga;
+
+	if (!dev)
+		return;
+
+	rga = dev_get_drvdata(dev);
+	if (!rga)
+		return;
+
+	mutex_lock(&rga->cmdlist_mutex);
+	list_for_each_entry_safe(node, n, &rga_priv->inuse_cmdlist, list) {
+		/*
+		 * unmap all gem objects not completed.
+		 *
+		 * P.S. if current process was terminated forcely then
+		 * there may be some commands in inuse_cmdlist so unmap
+		 * them.
+		 */
+		rga_unmap_cmdlist_gem(rga, node);
+		list_move_tail(&node->list, &rga->free_cmdlist);
+	}
+	mutex_unlock(&rga->cmdlist_mutex);
+
+	kfree(file_priv->rga_priv);
+}
+
+static void rga_runqueue_worker(struct work_struct *work)
+{
+	struct rockchip_rga *rga = container_of(work, struct rockchip_rga,
+					    runqueue_work);
+
+	mutex_lock(&rga->runqueue_mutex);
+	pm_runtime_put_sync(rga->dev);
+
+	complete(&rga->runqueue_node->complete);
+
+	if (rga->suspended)
+		rga->runqueue_node = NULL;
+	else
+		rga_exec_runqueue(rga);
+
+	mutex_unlock(&rga->runqueue_mutex);
+}
+
+static irqreturn_t rga_irq_handler(int irq, void *dev_id)
+{
+	struct rockchip_rga *rga = dev_id;
+	int intr;
+
+	intr = rga_read(rga, RGA_INT) & 0xf;
+
+	rga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
+
+	if (intr & 0x04)
+		queue_work(rga->rga_workq, &rga->runqueue_work);
+
+	return IRQ_HANDLED;
+}
+
+static int rga_parse_dt(struct rockchip_rga *rga)
+{
+	struct reset_control *sclk_rst, *aclk_rst, *hclk_rst;
+
+	sclk_rst = devm_reset_control_get(rga->dev, "sclk");
+	if (IS_ERR(sclk_rst)) {
+		dev_err(rga->dev, "failed to get sclk reset controller\n");
+		return PTR_ERR(sclk_rst);
+	}
+
+	aclk_rst = devm_reset_control_get(rga->dev, "aclk");
+	if (IS_ERR(aclk_rst)) {
+		dev_err(rga->dev, "failed to get aclk reset controller\n");
+		return PTR_ERR(aclk_rst);
+	}
+
+	hclk_rst = devm_reset_control_get(rga->dev, "hclk");
+	if (IS_ERR(hclk_rst)) {
+		dev_err(rga->dev, "failed to get hclk reset controller\n");
+		return PTR_ERR(hclk_rst);
+	}
+
+	reset_control_assert(sclk_rst);
+	usleep_range(10, 20);
+	reset_control_deassert(sclk_rst);
+
+	reset_control_assert(aclk_rst);
+	usleep_range(10, 20);
+	reset_control_deassert(aclk_rst);
+
+	reset_control_assert(hclk_rst);
+	usleep_range(10, 20);
+	reset_control_deassert(hclk_rst);
+
+	rga->sclk = devm_clk_get(rga->dev, "sclk");
+	if (IS_ERR(rga->sclk)) {
+		dev_err(rga->dev, "failed to get sclk clock\n");
+		return PTR_ERR(rga->sclk);
+	}
+
+	rga->aclk = devm_clk_get(rga->dev, "aclk");
+	if (IS_ERR(rga->aclk)) {
+		dev_err(rga->dev, "failed to get aclk clock\n");
+		return PTR_ERR(rga->aclk);
+	}
+
+	rga->hclk = devm_clk_get(rga->dev, "hclk");
+	if (IS_ERR(rga->hclk)) {
+		dev_err(rga->dev, "failed to get hclk clock\n");
+		return PTR_ERR(rga->hclk);
+	}
+
+	return rga_enable_clocks(rga);
+}
+
+static const struct of_device_id rockchip_rga_dt_ids[] = {
+	{ .compatible = "rockchip,rk3288-rga", },
+	{ .compatible = "rockchip,rk3228-rga", },
+	{ .compatible = "rockchip,rk3399-rga", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, rockchip_rga_dt_ids);
+
+static int rga_probe(struct platform_device *pdev)
+{
+	struct drm_rockchip_subdrv *subdrv;
+	struct rockchip_rga *rga;
+	struct resource *iores;
+	int irq;
+	int ret;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	rga = devm_kzalloc(&pdev->dev, sizeof(*rga), GFP_KERNEL);
+	if (!rga)
+		return -ENOMEM;
+
+	rga->dev = &pdev->dev;
+
+	rga->runqueue_slab = kmem_cache_create("rga_runqueue_slab",
+					       sizeof(struct rga_runqueue_node),
+					       0, 0, NULL);
+	if (!rga->runqueue_slab)
+		return -ENOMEM;
+
+	rga->rga_workq = create_singlethread_workqueue("rga");
+	if (!rga->rga_workq) {
+		dev_err(rga->dev, "failed to create workqueue\n");
+		goto err_destroy_slab;
+	}
+
+	INIT_WORK(&rga->runqueue_work, rga_runqueue_worker);
+	INIT_LIST_HEAD(&rga->runqueue_list);
+	mutex_init(&rga->runqueue_mutex);
+
+	INIT_LIST_HEAD(&rga->free_cmdlist);
+	mutex_init(&rga->cmdlist_mutex);
+
+	rga_init_cmdlist(rga);
+
+	ret = rga_parse_dt(rga);
+	if (ret) {
+		dev_err(rga->dev, "Unable to parse OF data\n");
+		goto err_destroy_workqueue;
+	}
+
+	pm_runtime_enable(rga->dev);
+
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	rga->regs = devm_ioremap_resource(rga->dev, iores);
+	if (IS_ERR(rga->regs)) {
+		ret = PTR_ERR(rga->regs);
+		goto err_put_clk;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(rga->dev, "failed to get irq\n");
+		ret = irq;
+		goto err_put_clk;
+	}
+
+	ret = devm_request_irq(rga->dev, irq, rga_irq_handler, 0,
+			       dev_name(rga->dev), rga);
+	if (ret < 0) {
+		dev_err(rga->dev, "failed to request irq\n");
+		goto err_put_clk;
+	}
+
+	platform_set_drvdata(pdev, rga);
+
+	rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
+	rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
+
+	subdrv = &rga->subdrv;
+	subdrv->dev = rga->dev;
+	subdrv->open = rockchip_rga_open;
+	subdrv->close = rockchip_rga_close;
+
+	rockchip_register_subdrv(subdrv);
+
+	return 0;
+
+err_put_clk:
+	pm_runtime_disable(rga->dev);
+err_destroy_workqueue:
+	destroy_workqueue(rga->rga_workq);
+err_destroy_slab:
+	kmem_cache_destroy(rga->runqueue_slab);
+
+	return ret;
+}
+
+static int rga_remove(struct platform_device *pdev)
+{
+	struct rockchip_rga *rga = platform_get_drvdata(pdev);
+
+	cancel_work_sync(&rga->runqueue_work);
+
+	while (rga->runqueue_node) {
+		rga_free_runqueue_node(rga, rga->runqueue_node);
+		rga->runqueue_node = rga_get_runqueue(rga);
+	}
+
+	rockchip_unregister_subdrv(&rga->subdrv);
+
+	return 0;
+}
+
+static int rga_suspend(struct device *dev)
+{
+	struct rockchip_rga *rga = dev_get_drvdata(dev);
+
+	mutex_lock(&rga->runqueue_mutex);
+	rga->suspended = true;
+	mutex_unlock(&rga->runqueue_mutex);
+
+	flush_work(&rga->runqueue_work);
+
+	return 0;
+}
+
+static int rga_resume(struct device *dev)
+{
+	struct rockchip_rga *rga = dev_get_drvdata(dev);
+
+	rga->suspended = false;
+	rga_exec_runqueue(rga);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int rga_runtime_suspend(struct device *dev)
+{
+	struct rockchip_rga *rga = dev_get_drvdata(dev);
+
+	rga_disable_clocks(rga);
+
+	return 0;
+}
+
+static int rga_runtime_resume(struct device *dev)
+{
+	struct rockchip_rga *rga = dev_get_drvdata(dev);
+
+	return rga_enable_clocks(rga);
+}
+#endif
+
+static const struct dev_pm_ops rga_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(rga_suspend, rga_resume)
+	SET_RUNTIME_PM_OPS(rga_runtime_suspend,
+			   rga_runtime_resume, NULL)
+};
+
+static struct platform_driver rga_pltfm_driver = {
+	.probe  = rga_probe,
+	.remove = rga_remove,
+	.driver = {
+		.name = "rockchip-rga",
+		.pm = &rga_pm,
+		.of_match_table = rockchip_rga_dt_ids,
+	},
+};
+
+module_platform_driver(rga_pltfm_driver);
+
+MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip RGA Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:rockchip-rga");
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_rga.h b/drivers/gpu/drm/rockchip/rockchip_drm_rga.h
new file mode 100644
index 0000000..4a8839a
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_rga.h
@@ -0,0 +1,108 @@
+#ifndef __ROCKCHIP_DRM_RGA__
+#define __ROCKCHIP_DRM_RGA__
+
+#define RGA_CMDBUF_SIZE			14
+#define RGA_CMDLIST_SIZE		0x20
+#define RGA_CMDLIST_NUM			64
+
+/* cmdlist data structure */
+struct rga_cmdlist {
+	u32		head;
+	unsigned long	data[RGA_CMDLIST_SIZE * 2];
+	u32		last;	/* last data offset */
+	void		*src_mmu_pages;
+	void		*dst_mmu_pages;
+	void		*src1_mmu_pages;
+	struct dma_buf_attachment *src_attach;
+	struct dma_buf_attachment *dst_attach;
+};
+
+struct rga_cmdlist_node {
+	struct list_head	list;
+	struct rga_cmdlist	cmdlist;
+};
+
+struct rga_runqueue_node {
+	struct list_head	list;
+
+	struct device		*dev;
+	pid_t			pid;
+	struct drm_file		*file;
+	struct completion	complete;
+
+	struct list_head	run_cmdlist;
+
+	int			cmdlist_cnt;
+	void			*cmdlist_pool_virt;
+	dma_addr_t		cmdlist_pool;
+	struct dma_attrs	cmdlist_dma_attrs;
+};
+
+struct rockchip_rga_version {
+	__u32			major;
+	__u32			minor;
+};
+
+struct rockchip_rga {
+	struct drm_device	*drm_dev;
+	struct device		*dev;
+	struct regmap		*grf;
+	void __iomem		*regs;
+	struct clk		*sclk;
+	struct clk		*aclk;
+	struct clk		*hclk;
+
+	bool				suspended;
+	struct rockchip_rga_version	version;
+	struct drm_rockchip_subdrv	subdrv;
+	struct workqueue_struct		*rga_workq;
+	struct work_struct		runqueue_work;
+
+	/* rga command list pool */
+	struct rga_cmdlist_node		cmdlist_node[RGA_CMDLIST_NUM];
+	struct mutex			cmdlist_mutex;
+
+	struct list_head		free_cmdlist;
+
+	/* rga runqueue */
+	struct rga_runqueue_node	*runqueue_node;
+	struct list_head		runqueue_list;
+	struct mutex			runqueue_mutex;
+	struct kmem_cache		*runqueue_slab;
+};
+
+struct rockchip_drm_rga_private {
+	struct device		*dev;
+	struct list_head	inuse_cmdlist;
+	struct list_head	userptr_list;
+};
+
+#ifdef CONFIG_ROCKCHIP_DRM_RGA
+int rockchip_rga_get_ver_ioctl(struct drm_device *dev, void *data,
+			       struct drm_file *file_priv);
+int rockchip_rga_set_cmdlist_ioctl(struct drm_device *dev, void *data,
+				   struct drm_file *file_priv);
+int rockchip_rga_exec_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv);
+#else
+static inline int rockchip_rga_get_ver_ioctl(struct drm_device *dev, void *data,
+					     struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int rockchip_rga_set_cmdlist_ioctl(struct drm_device *dev,
+						 void *data,
+						 struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int rockchip_rga_exec_ioctl(struct drm_device *dev, void *data,
+					  struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif /* __ROCKCHIP_DRM_RGA__ */
diff --git a/include/uapi/drm/rockchip_drm.h b/include/uapi/drm/rockchip_drm.h
new file mode 100644
index 0000000..2e3e240
--- /dev/null
+++ b/include/uapi/drm/rockchip_drm.h
@@ -0,0 +1,63 @@
+/* rockchip_drm.h
+ *
+ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ * Authors:
+ *	Yakir Yang <ykk@rock-chips.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _UAPI_ROCKCHIP_DRM_H_
+#define _UAPI_ROCKCHIP_DRM_H_
+
+#include <drm/drm.h>
+
+struct drm_rockchip_rga_get_ver {
+	__u32   major;
+	__u32   minor;
+};
+
+struct drm_rockchip_rga_cmd {
+	__u32   offset;
+	__u32   data;
+};
+
+enum drm_rockchip_rga_buf_type {
+	RGA_BUF_TYPE_USERPTR = 1 << 31,
+	RGA_BUF_TYPE_GEMFD   = 1 << 30,
+};
+
+struct drm_rockchip_rga_userptr {
+	unsigned long userptr;
+	unsigned long size;
+};
+
+struct drm_rockchip_rga_set_cmdlist {
+	__u64		cmd;
+	__u64		cmd_buf;
+	__u32		cmd_nr;
+	__u32		cmd_buf_nr;
+	__u64		user_data;
+};
+
+struct drm_rockchip_rga_exec {
+	__u64		async;
+};
+
+#define DRM_ROCKCHIP_RGA_GET_VER		0x20
+#define DRM_ROCKCHIP_RGA_SET_CMDLIST		0x21
+#define DRM_ROCKCHIP_RGA_EXEC			0x22
+
+#define DRM_IOCTL_ROCKCHIP_RGA_GET_VER		DRM_IOWR(DRM_COMMAND_BASE + \
+	DRM_ROCKCHIP_RGA_GET_VER, struct drm_rockchip_rga_get_ver)
+
+#define DRM_IOCTL_ROCKCHIP_RGA_SET_CMDLIST	DRM_IOWR(DRM_COMMAND_BASE + \
+	DRM_ROCKCHIP_RGA_SET_CMDLIST, struct drm_rockchip_rga_set_cmdlist)
+
+#define DRM_IOCTL_ROCKCHIP_RGA_EXEC		DRM_IOWR(DRM_COMMAND_BASE + \
+	DRM_ROCKCHIP_RGA_EXEC, struct drm_rockchip_rga_exec)
+
+#endif /* _UAPI_ROCKCHIP_DRM_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 2/4] drm: rockchip: add RGA driver support
@ 2016-03-21  9:40   ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:40 UTC (permalink / raw)
  To: David Airlie, Mark Yao, Heiko Stuebner
  Cc: devicetree, Russell King, Pawel Moll, Ian Campbell, linux-kernel,
	dri-devel, linux-rockchip, Rob Herring, Kumar Gala,
	linux-arm-kernel

Rockchip RGA is a separate 2D raster graphic acceleration unit. It
accelerates 2D graphics operations, such as point/line drawing, image
scaling, rotation, BitBLT, alpha blending and image blur/sharpness.

The RGA driver is based on Exynos G2D driver, it is performed by two
tasks simply.
1. Configures the rendering parameters, such as foreground color and
   coordinates data by setting the drawing context registers.
2. Start the rendering process by calling rga_exec() ioctl.

The RGA supports DMA mode as host interface. User can make command list
to reduce HOST(ARM) loads. The contents of The command list is setted to
relevant registers of RGA by DMA.

The command list is composed Header and command sets and Tail.
- Header: The number of command set(4Bytes)
- Command set: Register offset(4Bytes) + Register data(4Bytes)
- Tail: Pointer of base address of the other command list(4Bytes)

By Tail field, the G2D can process many command lists without halt at
one go.

The G2D has following the rendering pipeline.
               --->     Color Fill     --->
               |                          |
--> DMA (read) ---> Src Bitmap Process ----> Alpha/ROP ---> Format convert ---> DMA (Write)
               |                          |
               ---> Dst Bitmap Process --->

And supports various operations from the rendering pipeline.
- copy
- fast solid color fill
- rotation
- flip
- 4 operand raster operation(ROP4)
- alpha blending
- color key
- dithering
- etc

User should make the command list to data and registers needed by
operation to use. The Rockchip RGA driver only manages the command lists
received from user. Some registers needs memory base address(physical
address) of image. User doesn't know its physical address, so fills the
gem handle of that memory than address to command sets, then RGA driver
converts it to memory base address.

We adds three ioctls for Rockchip RGA.

- ioctls
DRM_ROCKCHIP_RGA_GET_VER: get the RGA hardware version
DRM_ROCKCHIP_RGA_SET_CMDLIST: set the command list from user to driver
DRM_ROCKCHIP_RGA_EXEC: execute the command lists setted to driver

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
 .../bindings/display/rockchip/rockchip-rga.txt     |  36 +
 drivers/gpu/drm/rockchip/Kconfig                   |   9 +
 drivers/gpu/drm/rockchip/Makefile                  |   1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c        |  35 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h        |   4 +
 drivers/gpu/drm/rockchip/rockchip_drm_rga.c        | 977 +++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_rga.h        | 108 +++
 include/uapi/drm/rockchip_drm.h                    |  63 ++
 8 files changed, 1232 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.h
 create mode 100644 include/uapi/drm/rockchip_drm.h

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
new file mode 100644
index 0000000..0c606cb
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
@@ -0,0 +1,36 @@
+device-tree bindings for rockchip 2D raster graphic acceleration controller (RGA)
+
+RGA is a separate 2D raster graphic acceleration unit. It accelerates 2D
+graphics operations, such as point/line drawing, image scaling, rotation,
+BitBLT, alpha blending and image blur/sharpness.
+
+Required properties:
+- compatible: value should be one of the following
+		"rockchip,rk3228-rga";
+		"rockchip,rk3288-rga";
+		"rockchip,rk3399-rga";
+
+- interrupts: RGA interrupt number.
+
+- clocks: phandle to RGA sclk/hclk/aclk clocks
+
+- clock-names: should be "aclk" "hclk" and "sclk"
+
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: should be "aclk" "hclk" and "sclk"
+
+Example:
+SoC specific DT entry:
+	rga: rga@ff680000 {
+		compatible = "rockchip,rk3399-rga";
+		reg = <0xff680000 0x10000>;
+		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "rga";
+		clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>;
+		clock-names = "aclk", "hclk", "sclk";
+
+		resets = <&cru SRST_A_RGA>, <&cru SRST_H_RGA>, <&cru SRST_RGA_CORE>;
+		reset-names = "aclk", "hclk", "sclk";
+		status = "disabled";
+	};
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 76b3362..220221b 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -16,6 +16,15 @@ config DRM_ROCKCHIP
 	  2D or 3D acceleration; acceleration is performed by other
 	  IP found on the SoC.
 
+config ROCKCHIP_DRM_RGA
+	tristate "Rockchip RGA support"
+	depends on DRM_ROCKCHIP
+	help
+	  Choose this option to enable support for Rockchip RGA.
+	  Rockchip RGA is a kind of hardware 2D accelerator, and it support
+	  solid roration, scaling, color format transform, say Y to enable its
+	  driver
+
 config ROCKCHIP_DW_HDMI
         tristate "Rockchip specific extensions for Synopsys DW HDMI"
         depends on DRM_ROCKCHIP
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index df8fbef..7de547c 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -9,5 +9,6 @@ rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
+obj-$(CONFIG_ROCKCHIP_DRM_RGA) += rockchip_drm_rga.o
 
 obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_vop_reg.o
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 4e0feb2..1638bc9 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -25,10 +25,13 @@
 #include <linux/of_graph.h>
 #include <linux/component.h>
 
+#include <drm/rockchip_drm.h>
+
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_fb.h"
 #include "rockchip_drm_fbdev.h"
 #include "rockchip_drm_gem.h"
+#include "rockchip_drm_rga.h"
 
 #define DRIVER_NAME	"rockchip"
 #define DRIVER_DESC	"RockChip Soc DRM"
@@ -277,16 +280,28 @@ EXPORT_SYMBOL_GPL(rockchip_unregister_subdrv);
 
 static int rockchip_drm_open(struct drm_device *dev, struct drm_file *file)
 {
+	struct rockchip_drm_file_private *file_priv;
 	struct drm_rockchip_subdrv *subdrv;
 	int ret = 0;
 
+	file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
+	if (!file_priv)
+		return -ENOMEM;
+
+	file->driver_priv = file_priv;
+
 	list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list) {
 		ret = subdrv->open(dev, subdrv->dev, file);
 		if (ret)
-			return ret;
+			goto err_file_priv_free;
 	}
 
 	return 0;
+
+err_file_priv_free:
+	kfree(file_priv);
+	file->driver_priv = NULL;
+	return ret;
 }
 
 static void rockchip_drm_preclose(struct drm_device *dev,
@@ -298,6 +313,12 @@ static void rockchip_drm_preclose(struct drm_device *dev,
 		subdrv->close(dev, subdrv->dev, file);
 }
 
+static void rockchip_drm_postclose(struct drm_device *dev,
+				   struct drm_file *file)
+{
+	kfree(file->driver_priv);
+}
+
 void rockchip_drm_lastclose(struct drm_device *dev)
 {
 	struct rockchip_drm_private *priv = dev->dev_private;
@@ -305,6 +326,15 @@ void rockchip_drm_lastclose(struct drm_device *dev)
 	drm_fb_helper_restore_fbdev_mode_unlocked(&priv->fbdev_helper);
 }
 
+static const struct drm_ioctl_desc rockchip_ioctls[] = {
+	DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_GET_VER, rockchip_rga_get_ver_ioctl,
+			  DRM_AUTH | DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_SET_CMDLIST, rockchip_rga_set_cmdlist_ioctl,
+			  DRM_AUTH | DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_EXEC, rockchip_rga_exec_ioctl,
+			  DRM_AUTH | DRM_RENDER_ALLOW),
+};
+
 static const struct file_operations rockchip_drm_driver_fops = {
 	.owner = THIS_MODULE,
 	.open = drm_open,
@@ -330,6 +360,7 @@ static struct drm_driver rockchip_drm_driver = {
 	.unload			= rockchip_drm_unload,
 	.open			= rockchip_drm_open,
 	.preclose		= rockchip_drm_preclose,
+	.postclose		= rockchip_drm_postclose,
 	.lastclose		= rockchip_drm_lastclose,
 	.get_vblank_counter	= drm_vblank_no_hw_counter,
 	.enable_vblank		= rockchip_drm_crtc_enable_vblank,
@@ -347,6 +378,8 @@ static struct drm_driver rockchip_drm_driver = {
 	.gem_prime_vmap		= rockchip_gem_prime_vmap,
 	.gem_prime_vunmap	= rockchip_gem_prime_vunmap,
 	.gem_prime_mmap		= rockchip_gem_mmap_buf,
+	.ioctls			= rockchip_ioctls,
+	.num_ioctls		= ARRAY_SIZE(rockchip_ioctls),
 	.fops			= &rockchip_drm_driver_fops,
 	.name	= DRIVER_NAME,
 	.desc	= DRIVER_DESC,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 5ea5fcb..ea30ba6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -53,6 +53,10 @@ struct drm_rockchip_subdrv {
 		      struct drm_file *file);
 };
 
+struct rockchip_drm_file_private {
+	struct rockchip_drm_rga_private *rga_priv;
+};
+
 struct rockchip_atomic_commit {
 	struct work_struct	work;
 	struct drm_atomic_state *state;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_rga.c b/drivers/gpu/drm/rockchip/rockchip_drm_rga.c
new file mode 100644
index 0000000..4202121
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_rga.c
@@ -0,0 +1,977 @@
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Yakir Yang <ykk@rock-chips.com>
+ *
+ * based on exynos_drm_g2d.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <drm/drmP.h>
+#include <drm/rockchip_drm.h>
+
+#include "rockchip_drm_drv.h"
+#include "rockchip_drm_rga.h"
+
+#define RGA_MODE_BASE_REG		0x0100
+#define RGA_MODE_MAX_REG		0x017C
+
+#define RGA_SYS_CTRL			0x0000
+#define RGA_CMD_CTRL			0x0004
+#define RGA_CMD_BASE			0x0008
+#define RGA_INT				0x0010
+#define RGA_MMU_CTRL0			0x0014
+#define RGA_VERSION_INFO		0x0028
+
+#define RGA_SRC_Y_RGB_BASE_ADDR		0x0108
+#define RGA_SRC_CB_BASE_ADDR		0x010C
+#define RGA_SRC_CR_BASE_ADDR		0x0110
+#define RGA_SRC1_RGB_BASE_ADDR		0x0114
+#define RGA_DST_Y_RGB_BASE_ADDR		0x013C
+#define RGA_DST_CB_BASE_ADDR		0x0140
+#define RGA_DST_CR_BASE_ADDR		0x014C
+#define RGA_MMU_CTRL1			0x016C
+#define RGA_MMU_SRC_BASE		0x0170
+#define RGA_MMU_SRC1_BASE		0x0174
+#define RGA_MMU_DST_BASE		0x0178
+
+static void rga_dma_flush_range(void *ptr, int size)
+{
+#ifdef CONFIG_ARM
+	dmac_flush_range(ptr, ptr + size);
+	outer_flush_range(virt_to_phys(ptr), virt_to_phys(ptr + size));
+#elif CONFIG_ARM64
+	__dma_flush_range(ptr, ptr + size);
+#endif
+}
+
+static inline void rga_write(struct rockchip_rga *rga, u32 reg, u32 value)
+{
+	writel(value, rga->regs + reg);
+}
+
+static inline u32 rga_read(struct rockchip_rga *rga, u32 reg)
+{
+	return readl(rga->regs + reg);
+}
+
+static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
+{
+	u32 temp = rga_read(rga, reg) & ~(mask);
+
+	temp |= val & mask;
+	rga_write(rga, reg, temp);
+}
+
+static int rga_enable_clocks(struct rockchip_rga *rga)
+{
+	int ret;
+
+	ret = clk_prepare_enable(rga->sclk);
+	if (ret) {
+		dev_err(rga->dev, "Cannot enable rga sclk: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(rga->aclk);
+	if (ret) {
+		dev_err(rga->dev, "Cannot enable rga aclk: %d\n", ret);
+		goto err_disable_sclk;
+	}
+
+	ret = clk_prepare_enable(rga->hclk);
+	if (ret) {
+		dev_err(rga->dev, "Cannot enable rga hclk: %d\n", ret);
+		goto err_disable_aclk;
+	}
+
+	return 0;
+
+err_disable_sclk:
+	clk_disable_unprepare(rga->sclk);
+err_disable_aclk:
+	clk_disable_unprepare(rga->aclk);
+
+	return ret;
+}
+
+static void rga_disable_clocks(struct rockchip_rga *rga)
+{
+	clk_disable_unprepare(rga->sclk);
+	clk_disable_unprepare(rga->hclk);
+	clk_disable_unprepare(rga->aclk);
+}
+
+static void rga_init_cmdlist(struct rockchip_rga *rga)
+{
+	struct rga_cmdlist_node *node;
+	int nr;
+
+	node = rga->cmdlist_node;
+
+	for (nr = 0; nr < ARRAY_SIZE(rga->cmdlist_node); nr++)
+		list_add_tail(&node[nr].list, &rga->free_cmdlist);
+}
+
+static int rga_alloc_dma_buf_for_cmdlist(struct rga_runqueue_node *runqueue)
+{
+	struct list_head *run_cmdlist = &runqueue->run_cmdlist;
+	struct device *dev = runqueue->dev;
+	struct dma_attrs cmdlist_dma_attrs;
+	struct rga_cmdlist_node *node;
+	void *cmdlist_pool_virt;
+	dma_addr_t cmdlist_pool;
+	int cmdlist_cnt = 0;
+	int count = 0;
+
+	list_for_each_entry(node, run_cmdlist, list)
+		cmdlist_cnt++;
+
+	init_dma_attrs(&cmdlist_dma_attrs);
+	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &runqueue->cmdlist_dma_attrs);
+
+	cmdlist_pool_virt = dma_alloc_attrs(dev, cmdlist_cnt * RGA_CMDLIST_SIZE,
+					    &cmdlist_pool, GFP_KERNEL,
+					    &cmdlist_dma_attrs);
+	if (!cmdlist_pool_virt) {
+		dev_err(dev, "failed to allocate cmdlist dma memory\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * Fill in the RGA operation registers from cmdlist command buffer,
+	 * and also filled in the MMU TLB base information.
+	 */
+	list_for_each_entry(node, run_cmdlist, list) {
+		struct rga_cmdlist *cmdlist = &node->cmdlist;
+		unsigned int mmu_ctrl = 0;
+		unsigned int *dest;
+		unsigned int reg;
+		int i;
+
+		dest = cmdlist_pool_virt + RGA_CMDLIST_SIZE * 4 * count++;
+
+		for (i = 0; i < cmdlist->last / 2; i++) {
+			reg = (node->cmdlist.data[2 * i] - RGA_MODE_BASE_REG);
+			if (reg > RGA_MODE_BASE_REG)
+				continue;
+			dest[reg << 2] = cmdlist->data[2 * i + 1];
+		}
+
+		if (cmdlist->src_mmu_pages) {
+			reg = RGA_MMU_SRC_BASE - RGA_MODE_BASE_REG;
+			dest[reg << 2] = virt_to_phys(cmdlist->src_mmu_pages) >> 4;
+			mmu_ctrl |= 0x7;
+		}
+
+		if (cmdlist->dst_mmu_pages) {
+			reg = RGA_MMU_DST_BASE - RGA_MODE_BASE_REG;
+			dest[reg << 2] = virt_to_phys(cmdlist->dst_mmu_pages) >> 4;
+			mmu_ctrl |= 0x7 << 8;
+		}
+
+		if (cmdlist->src1_mmu_pages) {
+			reg = RGA_MMU_SRC1_BASE - RGA_MODE_BASE_REG;
+			dest[reg << 2] = virt_to_phys(cmdlist->src1_mmu_pages) >> 4;
+			mmu_ctrl |= 0x7 << 4;
+		}
+
+		reg = RGA_MMU_CTRL1 - RGA_MODE_BASE_REG;
+		dest[reg << 2] = mmu_ctrl;
+	}
+
+	rga_dma_flush_range(cmdlist_pool_virt, cmdlist_cnt * RGA_CMDLIST_SIZE);
+
+	runqueue->cmdlist_dma_attrs = cmdlist_dma_attrs;
+	runqueue->cmdlist_pool_virt = cmdlist_pool_virt;
+	runqueue->cmdlist_pool = cmdlist_pool;
+	runqueue->cmdlist_cnt = cmdlist_cnt;
+
+	return 0;
+}
+
+static int rga_check_reg_offset(struct device *dev,
+				struct rga_cmdlist_node *node)
+{
+	struct rga_cmdlist *cmdlist = &node->cmdlist;
+	int index;
+	int reg;
+	int i;
+
+	for (i = 0; i < cmdlist->last / 2; i++) {
+		index = cmdlist->last - 2 * (i + 1);
+		reg = cmdlist->data[index];
+
+		switch (reg) {
+		case RGA_BUF_TYPE_GEMFD | RGA_DST_Y_RGB_BASE_ADDR:
+		case RGA_BUF_TYPE_GEMFD | RGA_SRC_Y_RGB_BASE_ADDR:
+			break;
+
+		case RGA_BUF_TYPE_USERPTR | RGA_DST_Y_RGB_BASE_ADDR:
+		case RGA_BUF_TYPE_USERPTR | RGA_SRC_Y_RGB_BASE_ADDR:
+			goto err;
+
+		default:
+			if (reg < RGA_MODE_BASE_REG || reg > RGA_MODE_MAX_REG)
+				goto err;
+
+			if (reg % 4)
+				goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	dev_err(dev, "Bad register offset: 0x%lx\n", cmdlist->data[index]);
+	return -EINVAL;
+}
+
+static struct dma_buf_attachment *
+rga_gem_buf_to_pages(struct rockchip_rga *rga, void **mmu_pages, int fd)
+{
+	struct dma_buf_attachment *attach;
+	struct dma_buf *dmabuf;
+	struct sg_table *sgt;
+	struct scatterlist *sgl;
+	unsigned int mapped_size = 0;
+	unsigned int address;
+	unsigned int len;
+	unsigned int i, p;
+	unsigned int *pages;
+	int ret;
+
+	dmabuf = dma_buf_get(fd);
+	if (IS_ERR(dmabuf)) {
+		dev_err(rga->dev, "Failed to get dma_buf with fd %d\n", fd);
+		return ERR_PTR(-EINVAL);
+	}
+
+	attach = dma_buf_attach(dmabuf, rga->dev);
+	if (IS_ERR(attach)) {
+		dev_err(rga->dev, "Failed to attach dma_buf\n");
+		ret = PTR_ERR(attach);
+		goto failed_attach;
+	}
+
+	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+	if (IS_ERR(sgt)) {
+		dev_err(rga->dev, "Failed to map dma_buf attachment\n");
+		ret = PTR_ERR(sgt);
+		goto failed_detach;
+	}
+
+	/*
+	 * Alloc (2^3 * 4K) = 32K byte for storing pages, those space could
+	 * cover 32K * 4K = 128M ram address.
+	 */
+	pages = (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
+
+	for_each_sg(sgt->sgl, sgl, sgt->nents, i) {
+		len = sg_dma_len(sgl) >> PAGE_SHIFT;
+		address = sg_phys(sgl);
+
+		for (p = 0; p < len; p++) {
+			dma_addr_t phys = address + (p << PAGE_SHIFT);
+			void *virt = phys_to_virt(phys);
+
+			rga_dma_flush_range(virt, 4 * 1024);
+			pages[mapped_size + p] = phys;
+		}
+
+		mapped_size += len;
+	}
+
+	rga_dma_flush_range(pages, 32 * 1024);
+
+	*mmu_pages = pages;
+
+	dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+
+	return attach;
+
+failed_detach:
+	dma_buf_detach(dmabuf, attach);
+failed_attach:
+	dma_buf_put(dmabuf);
+
+	return ERR_PTR(ret);
+}
+
+static int rga_map_cmdlist_gem(struct rockchip_rga *rga,
+			       struct rga_cmdlist_node *node,
+			       struct drm_device *drm_dev,
+			       struct drm_file *file)
+{
+	struct rga_cmdlist *cmdlist = &node->cmdlist;
+	struct dma_buf_attachment *attach;
+	void *mmu_pages;
+	int fd;
+	int i;
+
+	for (i = 0; i < cmdlist->last / 2; i++) {
+		int index = cmdlist->last - 2 * (i + 1);
+
+		switch (cmdlist->data[index]) {
+		case RGA_SRC_Y_RGB_BASE_ADDR | RGA_BUF_TYPE_GEMFD:
+			fd = cmdlist->data[index + 1];
+			attach = rga_gem_buf_to_pages(rga, &mmu_pages, fd);
+
+			cmdlist->src_attach = attach;
+			cmdlist->src_mmu_pages = mmu_pages;
+			break;
+
+		case RGA_DST_Y_RGB_BASE_ADDR | RGA_BUF_TYPE_GEMFD:
+			fd = cmdlist->data[index + 1];
+			attach = rga_gem_buf_to_pages(rga, &mmu_pages, fd);
+
+			cmdlist->dst_attach = attach;
+			cmdlist->dst_mmu_pages = mmu_pages;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static void rga_unmap_cmdlist_gem(struct rockchip_rga *rga,
+				  struct rga_cmdlist_node *node)
+{
+	struct dma_buf_attachment *attach;
+	struct dma_buf *dma_buf;
+
+	attach = node->cmdlist.src_attach;
+	if (attach) {
+		dma_buf = attach->dmabuf;
+		dma_buf_detach(dma_buf, attach);
+		dma_buf_put(dma_buf);
+	}
+	node->cmdlist.src_attach = NULL;
+
+	attach = node->cmdlist.dst_attach;
+	if (attach) {
+		dma_buf = attach->dmabuf;
+		dma_buf_detach(dma_buf, attach);
+		dma_buf_put(dma_buf);
+	}
+	node->cmdlist.dst_attach = NULL;
+
+	if (node->cmdlist.src_mmu_pages)
+		free_pages((unsigned long)node->cmdlist.src_mmu_pages, 3);
+	node->cmdlist.src_mmu_pages = NULL;
+
+	if (node->cmdlist.src1_mmu_pages)
+		free_pages((unsigned long)node->cmdlist.src1_mmu_pages, 3);
+	node->cmdlist.src1_mmu_pages = NULL;
+
+	if (node->cmdlist.dst_mmu_pages)
+		free_pages((unsigned long)node->cmdlist.dst_mmu_pages, 3);
+	node->cmdlist.dst_mmu_pages = NULL;
+}
+
+static void rga_cmd_start(struct rockchip_rga *rga,
+			  struct rga_runqueue_node *runqueue)
+{
+	int ret;
+
+	ret = pm_runtime_get_sync(rga->dev);
+	if (ret < 0)
+		return;
+
+	rga_write(rga, RGA_SYS_CTRL, 0x00);
+
+	rga_write(rga, RGA_CMD_BASE, runqueue->cmdlist_pool);
+
+	rga_write(rga, RGA_SYS_CTRL, 0x22);
+
+	rga_write(rga, RGA_INT, 0x600);
+
+	rga_write(rga, RGA_CMD_CTRL, ((runqueue->cmdlist_cnt - 1) << 3) | 0x1);
+}
+
+static void rga_free_runqueue_node(struct rockchip_rga *rga,
+				   struct rga_runqueue_node *runqueue)
+{
+	struct rga_cmdlist_node *node;
+
+	if (!runqueue)
+		return;
+
+	if (runqueue->cmdlist_pool_virt && runqueue->cmdlist_pool)
+		dma_free_attrs(rga->dev, runqueue->cmdlist_cnt * RGA_CMDLIST_SIZE,
+			       runqueue->cmdlist_pool_virt,
+			       runqueue->cmdlist_pool,
+			       &runqueue->cmdlist_dma_attrs);
+
+	mutex_lock(&rga->cmdlist_mutex);
+	/*
+	 * commands in run_cmdlist have been completed so unmap all gem
+	 * objects in each command node so that they are unreferenced.
+	 */
+	list_for_each_entry(node, &runqueue->run_cmdlist, list)
+		rga_unmap_cmdlist_gem(rga, node);
+	list_splice_tail_init(&runqueue->run_cmdlist, &rga->free_cmdlist);
+	mutex_unlock(&rga->cmdlist_mutex);
+
+	kmem_cache_free(rga->runqueue_slab, runqueue);
+}
+
+static struct rga_runqueue_node *rga_get_runqueue(struct rockchip_rga *rga)
+{
+	struct rga_runqueue_node *runqueue;
+
+	if (list_empty(&rga->runqueue_list))
+		return NULL;
+
+	runqueue = list_first_entry(&rga->runqueue_list,
+				    struct rga_runqueue_node, list);
+	list_del_init(&runqueue->list);
+
+	return runqueue;
+}
+
+static void rga_exec_runqueue(struct rockchip_rga *rga)
+{
+	rga->runqueue_node = rga_get_runqueue(rga);
+	if (rga->runqueue_node)
+		rga_cmd_start(rga, rga->runqueue_node);
+}
+
+static struct rga_cmdlist_node *rga_get_cmdlist(struct rockchip_rga *rga)
+{
+	struct rga_cmdlist_node *node;
+	struct device *dev = rga->dev;
+
+	mutex_lock(&rga->cmdlist_mutex);
+	if (list_empty(&rga->free_cmdlist)) {
+		dev_err(dev, "there is no free cmdlist\n");
+		mutex_unlock(&rga->cmdlist_mutex);
+		return NULL;
+	}
+
+	node = list_first_entry(&rga->free_cmdlist,
+				struct rga_cmdlist_node, list);
+	list_del_init(&node->list);
+	mutex_unlock(&rga->cmdlist_mutex);
+
+	return node;
+}
+
+static void rga_add_cmdlist_to_inuse(struct rockchip_drm_rga_private *rga_priv,
+				     struct rga_cmdlist_node *node)
+{
+	struct rga_cmdlist_node *lnode;
+
+	if (list_empty(&rga_priv->inuse_cmdlist))
+		goto add_to_list;
+
+	/* this links to base address of new cmdlist */
+	lnode = list_entry(rga_priv->inuse_cmdlist.prev,
+			   struct rga_cmdlist_node, list);
+
+add_to_list:
+	list_add_tail(&node->list, &rga_priv->inuse_cmdlist);
+}
+
+/*
+ * IOCRL functions for userspace to get RGA version.
+ */
+int rockchip_rga_get_ver_ioctl(struct drm_device *drm_dev, void *data,
+			       struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
+	struct drm_rockchip_rga_get_ver *ver = data;
+	struct rockchip_rga *rga;
+	struct device *dev;
+
+	if (!rga_priv)
+		return -ENODEV;
+
+	dev = rga_priv->dev;
+	if (!dev)
+		return -ENODEV;
+
+	rga = dev_get_drvdata(dev);
+	if (!rga)
+		return -EFAULT;
+
+	ver->major = rga->version.major;
+	ver->minor = rga->version.minor;
+
+	return 0;
+}
+
+/*
+ * IOCRL functions for userspace to send an RGA request.
+ */
+int rockchip_rga_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
+				   struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
+	struct drm_rockchip_rga_set_cmdlist *req = data;
+	struct rga_cmdlist_node *node;
+	struct rga_cmdlist *cmdlist;
+	struct rockchip_rga *rga;
+	int ret;
+
+	if (!rga_priv)
+		return -ENODEV;
+
+	if (!rga_priv->dev)
+		return -ENODEV;
+
+	rga = dev_get_drvdata(rga_priv->dev);
+	if (!rga)
+		return -EFAULT;
+
+	node = rga_get_cmdlist(rga);
+	if (!node)
+		return -ENOMEM;
+
+	cmdlist = &node->cmdlist;
+	cmdlist->last = 0;
+
+	if (req->cmd_nr > RGA_CMDLIST_SIZE || req->cmd_buf_nr > RGA_CMDBUF_SIZE) {
+		dev_err(rga->dev, "cmdlist size is too big\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Copy the command / buffer registers setting from userspace, each
+	 * command have two integer, one for register offset, another for
+	 * register value.
+	 */
+	if (copy_from_user((void *)cmdlist->data, (const void __user *)req->cmd,
+			   sizeof(struct drm_rockchip_rga_cmd) * req->cmd_nr))
+		return -EFAULT;
+	cmdlist->last += req->cmd_nr * 2;
+
+	if (copy_from_user((void *)cmdlist->data + cmdlist->last,
+			   (const void __user *)req->cmd_buf,
+			   sizeof(struct drm_rockchip_rga_cmd) * req->cmd_buf_nr))
+		return -EFAULT;
+	cmdlist->last += req->cmd_buf_nr * 2;
+
+	/*
+	 * Check the userspace command registers, and mapping the framebuffer,
+	 * create the RGA mmu pages or get the framebuffer dma address.
+	 */
+	ret = rga_check_reg_offset(rga->dev, node);
+	if (ret < 0)
+		return ret;
+
+	ret = rga_map_cmdlist_gem(rga, node, drm_dev, file);
+	if (ret < 0)
+		return ret;
+
+	rga_add_cmdlist_to_inuse(rga_priv, node);
+
+	return 0;
+}
+
+/*
+ * IOCRL functions for userspace to start RGA transform.
+ */
+int rockchip_rga_exec_ioctl(struct drm_device *drm_dev, void *data,
+			    struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
+	struct rga_runqueue_node *runqueue;
+	struct rockchip_rga *rga;
+	struct device *dev;
+	int ret;
+
+	if (!rga_priv)
+		return -ENODEV;
+
+	dev = rga_priv->dev;
+	if (!dev)
+		return -ENODEV;
+
+	rga = dev_get_drvdata(dev);
+	if (!rga)
+		return -EFAULT;
+
+	runqueue = kmem_cache_alloc(rga->runqueue_slab, GFP_KERNEL);
+	if (!runqueue) {
+		dev_err(rga->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	runqueue->dev = rga->dev;
+
+	init_completion(&runqueue->complete);
+
+	INIT_LIST_HEAD(&runqueue->run_cmdlist);
+
+	list_splice_init(&rga_priv->inuse_cmdlist, &runqueue->run_cmdlist);
+
+	if (list_empty(&runqueue->run_cmdlist)) {
+		dev_err(rga->dev, "there is no inuse cmdlist\n");
+		kmem_cache_free(rga->runqueue_slab, runqueue);
+		return -EPERM;
+	}
+
+	ret = rga_alloc_dma_buf_for_cmdlist(runqueue);
+	if (ret < 0) {
+		dev_err(rga->dev, "cmdlist init failed\n");
+		return ret;
+	}
+
+	mutex_lock(&rga->runqueue_mutex);
+	runqueue->pid = current->pid;
+	runqueue->file = file;
+	list_add_tail(&runqueue->list, &rga->runqueue_list);
+	if (!rga->runqueue_node)
+		rga_exec_runqueue(rga);
+	mutex_unlock(&rga->runqueue_mutex);
+
+	wait_for_completion(&runqueue->complete);
+	rga_free_runqueue_node(rga, runqueue);
+
+	return 0;
+}
+
+static int rockchip_rga_open(struct drm_device *drm_dev, struct device *dev,
+			     struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv;
+
+	rga_priv = kzalloc(sizeof(*rga_priv), GFP_KERNEL);
+	if (!rga_priv)
+		return -ENOMEM;
+
+	rga_priv->dev = dev;
+	file_priv->rga_priv = rga_priv;
+
+	INIT_LIST_HEAD(&rga_priv->inuse_cmdlist);
+
+	return 0;
+}
+
+static void rockchip_rga_close(struct drm_device *drm_dev, struct device *dev,
+			       struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
+	struct rga_cmdlist_node *node, *n;
+	struct rockchip_rga *rga;
+
+	if (!dev)
+		return;
+
+	rga = dev_get_drvdata(dev);
+	if (!rga)
+		return;
+
+	mutex_lock(&rga->cmdlist_mutex);
+	list_for_each_entry_safe(node, n, &rga_priv->inuse_cmdlist, list) {
+		/*
+		 * unmap all gem objects not completed.
+		 *
+		 * P.S. if current process was terminated forcely then
+		 * there may be some commands in inuse_cmdlist so unmap
+		 * them.
+		 */
+		rga_unmap_cmdlist_gem(rga, node);
+		list_move_tail(&node->list, &rga->free_cmdlist);
+	}
+	mutex_unlock(&rga->cmdlist_mutex);
+
+	kfree(file_priv->rga_priv);
+}
+
+static void rga_runqueue_worker(struct work_struct *work)
+{
+	struct rockchip_rga *rga = container_of(work, struct rockchip_rga,
+					    runqueue_work);
+
+	mutex_lock(&rga->runqueue_mutex);
+	pm_runtime_put_sync(rga->dev);
+
+	complete(&rga->runqueue_node->complete);
+
+	if (rga->suspended)
+		rga->runqueue_node = NULL;
+	else
+		rga_exec_runqueue(rga);
+
+	mutex_unlock(&rga->runqueue_mutex);
+}
+
+static irqreturn_t rga_irq_handler(int irq, void *dev_id)
+{
+	struct rockchip_rga *rga = dev_id;
+	int intr;
+
+	intr = rga_read(rga, RGA_INT) & 0xf;
+
+	rga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
+
+	if (intr & 0x04)
+		queue_work(rga->rga_workq, &rga->runqueue_work);
+
+	return IRQ_HANDLED;
+}
+
+static int rga_parse_dt(struct rockchip_rga *rga)
+{
+	struct reset_control *sclk_rst, *aclk_rst, *hclk_rst;
+
+	sclk_rst = devm_reset_control_get(rga->dev, "sclk");
+	if (IS_ERR(sclk_rst)) {
+		dev_err(rga->dev, "failed to get sclk reset controller\n");
+		return PTR_ERR(sclk_rst);
+	}
+
+	aclk_rst = devm_reset_control_get(rga->dev, "aclk");
+	if (IS_ERR(aclk_rst)) {
+		dev_err(rga->dev, "failed to get aclk reset controller\n");
+		return PTR_ERR(aclk_rst);
+	}
+
+	hclk_rst = devm_reset_control_get(rga->dev, "hclk");
+	if (IS_ERR(hclk_rst)) {
+		dev_err(rga->dev, "failed to get hclk reset controller\n");
+		return PTR_ERR(hclk_rst);
+	}
+
+	reset_control_assert(sclk_rst);
+	usleep_range(10, 20);
+	reset_control_deassert(sclk_rst);
+
+	reset_control_assert(aclk_rst);
+	usleep_range(10, 20);
+	reset_control_deassert(aclk_rst);
+
+	reset_control_assert(hclk_rst);
+	usleep_range(10, 20);
+	reset_control_deassert(hclk_rst);
+
+	rga->sclk = devm_clk_get(rga->dev, "sclk");
+	if (IS_ERR(rga->sclk)) {
+		dev_err(rga->dev, "failed to get sclk clock\n");
+		return PTR_ERR(rga->sclk);
+	}
+
+	rga->aclk = devm_clk_get(rga->dev, "aclk");
+	if (IS_ERR(rga->aclk)) {
+		dev_err(rga->dev, "failed to get aclk clock\n");
+		return PTR_ERR(rga->aclk);
+	}
+
+	rga->hclk = devm_clk_get(rga->dev, "hclk");
+	if (IS_ERR(rga->hclk)) {
+		dev_err(rga->dev, "failed to get hclk clock\n");
+		return PTR_ERR(rga->hclk);
+	}
+
+	return rga_enable_clocks(rga);
+}
+
+static const struct of_device_id rockchip_rga_dt_ids[] = {
+	{ .compatible = "rockchip,rk3288-rga", },
+	{ .compatible = "rockchip,rk3228-rga", },
+	{ .compatible = "rockchip,rk3399-rga", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, rockchip_rga_dt_ids);
+
+static int rga_probe(struct platform_device *pdev)
+{
+	struct drm_rockchip_subdrv *subdrv;
+	struct rockchip_rga *rga;
+	struct resource *iores;
+	int irq;
+	int ret;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	rga = devm_kzalloc(&pdev->dev, sizeof(*rga), GFP_KERNEL);
+	if (!rga)
+		return -ENOMEM;
+
+	rga->dev = &pdev->dev;
+
+	rga->runqueue_slab = kmem_cache_create("rga_runqueue_slab",
+					       sizeof(struct rga_runqueue_node),
+					       0, 0, NULL);
+	if (!rga->runqueue_slab)
+		return -ENOMEM;
+
+	rga->rga_workq = create_singlethread_workqueue("rga");
+	if (!rga->rga_workq) {
+		dev_err(rga->dev, "failed to create workqueue\n");
+		goto err_destroy_slab;
+	}
+
+	INIT_WORK(&rga->runqueue_work, rga_runqueue_worker);
+	INIT_LIST_HEAD(&rga->runqueue_list);
+	mutex_init(&rga->runqueue_mutex);
+
+	INIT_LIST_HEAD(&rga->free_cmdlist);
+	mutex_init(&rga->cmdlist_mutex);
+
+	rga_init_cmdlist(rga);
+
+	ret = rga_parse_dt(rga);
+	if (ret) {
+		dev_err(rga->dev, "Unable to parse OF data\n");
+		goto err_destroy_workqueue;
+	}
+
+	pm_runtime_enable(rga->dev);
+
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	rga->regs = devm_ioremap_resource(rga->dev, iores);
+	if (IS_ERR(rga->regs)) {
+		ret = PTR_ERR(rga->regs);
+		goto err_put_clk;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(rga->dev, "failed to get irq\n");
+		ret = irq;
+		goto err_put_clk;
+	}
+
+	ret = devm_request_irq(rga->dev, irq, rga_irq_handler, 0,
+			       dev_name(rga->dev), rga);
+	if (ret < 0) {
+		dev_err(rga->dev, "failed to request irq\n");
+		goto err_put_clk;
+	}
+
+	platform_set_drvdata(pdev, rga);
+
+	rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
+	rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
+
+	subdrv = &rga->subdrv;
+	subdrv->dev = rga->dev;
+	subdrv->open = rockchip_rga_open;
+	subdrv->close = rockchip_rga_close;
+
+	rockchip_register_subdrv(subdrv);
+
+	return 0;
+
+err_put_clk:
+	pm_runtime_disable(rga->dev);
+err_destroy_workqueue:
+	destroy_workqueue(rga->rga_workq);
+err_destroy_slab:
+	kmem_cache_destroy(rga->runqueue_slab);
+
+	return ret;
+}
+
+static int rga_remove(struct platform_device *pdev)
+{
+	struct rockchip_rga *rga = platform_get_drvdata(pdev);
+
+	cancel_work_sync(&rga->runqueue_work);
+
+	while (rga->runqueue_node) {
+		rga_free_runqueue_node(rga, rga->runqueue_node);
+		rga->runqueue_node = rga_get_runqueue(rga);
+	}
+
+	rockchip_unregister_subdrv(&rga->subdrv);
+
+	return 0;
+}
+
+static int rga_suspend(struct device *dev)
+{
+	struct rockchip_rga *rga = dev_get_drvdata(dev);
+
+	mutex_lock(&rga->runqueue_mutex);
+	rga->suspended = true;
+	mutex_unlock(&rga->runqueue_mutex);
+
+	flush_work(&rga->runqueue_work);
+
+	return 0;
+}
+
+static int rga_resume(struct device *dev)
+{
+	struct rockchip_rga *rga = dev_get_drvdata(dev);
+
+	rga->suspended = false;
+	rga_exec_runqueue(rga);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int rga_runtime_suspend(struct device *dev)
+{
+	struct rockchip_rga *rga = dev_get_drvdata(dev);
+
+	rga_disable_clocks(rga);
+
+	return 0;
+}
+
+static int rga_runtime_resume(struct device *dev)
+{
+	struct rockchip_rga *rga = dev_get_drvdata(dev);
+
+	return rga_enable_clocks(rga);
+}
+#endif
+
+static const struct dev_pm_ops rga_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(rga_suspend, rga_resume)
+	SET_RUNTIME_PM_OPS(rga_runtime_suspend,
+			   rga_runtime_resume, NULL)
+};
+
+static struct platform_driver rga_pltfm_driver = {
+	.probe  = rga_probe,
+	.remove = rga_remove,
+	.driver = {
+		.name = "rockchip-rga",
+		.pm = &rga_pm,
+		.of_match_table = rockchip_rga_dt_ids,
+	},
+};
+
+module_platform_driver(rga_pltfm_driver);
+
+MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip RGA Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:rockchip-rga");
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_rga.h b/drivers/gpu/drm/rockchip/rockchip_drm_rga.h
new file mode 100644
index 0000000..4a8839a
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_rga.h
@@ -0,0 +1,108 @@
+#ifndef __ROCKCHIP_DRM_RGA__
+#define __ROCKCHIP_DRM_RGA__
+
+#define RGA_CMDBUF_SIZE			14
+#define RGA_CMDLIST_SIZE		0x20
+#define RGA_CMDLIST_NUM			64
+
+/* cmdlist data structure */
+struct rga_cmdlist {
+	u32		head;
+	unsigned long	data[RGA_CMDLIST_SIZE * 2];
+	u32		last;	/* last data offset */
+	void		*src_mmu_pages;
+	void		*dst_mmu_pages;
+	void		*src1_mmu_pages;
+	struct dma_buf_attachment *src_attach;
+	struct dma_buf_attachment *dst_attach;
+};
+
+struct rga_cmdlist_node {
+	struct list_head	list;
+	struct rga_cmdlist	cmdlist;
+};
+
+struct rga_runqueue_node {
+	struct list_head	list;
+
+	struct device		*dev;
+	pid_t			pid;
+	struct drm_file		*file;
+	struct completion	complete;
+
+	struct list_head	run_cmdlist;
+
+	int			cmdlist_cnt;
+	void			*cmdlist_pool_virt;
+	dma_addr_t		cmdlist_pool;
+	struct dma_attrs	cmdlist_dma_attrs;
+};
+
+struct rockchip_rga_version {
+	__u32			major;
+	__u32			minor;
+};
+
+struct rockchip_rga {
+	struct drm_device	*drm_dev;
+	struct device		*dev;
+	struct regmap		*grf;
+	void __iomem		*regs;
+	struct clk		*sclk;
+	struct clk		*aclk;
+	struct clk		*hclk;
+
+	bool				suspended;
+	struct rockchip_rga_version	version;
+	struct drm_rockchip_subdrv	subdrv;
+	struct workqueue_struct		*rga_workq;
+	struct work_struct		runqueue_work;
+
+	/* rga command list pool */
+	struct rga_cmdlist_node		cmdlist_node[RGA_CMDLIST_NUM];
+	struct mutex			cmdlist_mutex;
+
+	struct list_head		free_cmdlist;
+
+	/* rga runqueue */
+	struct rga_runqueue_node	*runqueue_node;
+	struct list_head		runqueue_list;
+	struct mutex			runqueue_mutex;
+	struct kmem_cache		*runqueue_slab;
+};
+
+struct rockchip_drm_rga_private {
+	struct device		*dev;
+	struct list_head	inuse_cmdlist;
+	struct list_head	userptr_list;
+};
+
+#ifdef CONFIG_ROCKCHIP_DRM_RGA
+int rockchip_rga_get_ver_ioctl(struct drm_device *dev, void *data,
+			       struct drm_file *file_priv);
+int rockchip_rga_set_cmdlist_ioctl(struct drm_device *dev, void *data,
+				   struct drm_file *file_priv);
+int rockchip_rga_exec_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv);
+#else
+static inline int rockchip_rga_get_ver_ioctl(struct drm_device *dev, void *data,
+					     struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int rockchip_rga_set_cmdlist_ioctl(struct drm_device *dev,
+						 void *data,
+						 struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int rockchip_rga_exec_ioctl(struct drm_device *dev, void *data,
+					  struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif /* __ROCKCHIP_DRM_RGA__ */
diff --git a/include/uapi/drm/rockchip_drm.h b/include/uapi/drm/rockchip_drm.h
new file mode 100644
index 0000000..2e3e240
--- /dev/null
+++ b/include/uapi/drm/rockchip_drm.h
@@ -0,0 +1,63 @@
+/* rockchip_drm.h
+ *
+ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ * Authors:
+ *	Yakir Yang <ykk@rock-chips.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _UAPI_ROCKCHIP_DRM_H_
+#define _UAPI_ROCKCHIP_DRM_H_
+
+#include <drm/drm.h>
+
+struct drm_rockchip_rga_get_ver {
+	__u32   major;
+	__u32   minor;
+};
+
+struct drm_rockchip_rga_cmd {
+	__u32   offset;
+	__u32   data;
+};
+
+enum drm_rockchip_rga_buf_type {
+	RGA_BUF_TYPE_USERPTR = 1 << 31,
+	RGA_BUF_TYPE_GEMFD   = 1 << 30,
+};
+
+struct drm_rockchip_rga_userptr {
+	unsigned long userptr;
+	unsigned long size;
+};
+
+struct drm_rockchip_rga_set_cmdlist {
+	__u64		cmd;
+	__u64		cmd_buf;
+	__u32		cmd_nr;
+	__u32		cmd_buf_nr;
+	__u64		user_data;
+};
+
+struct drm_rockchip_rga_exec {
+	__u64		async;
+};
+
+#define DRM_ROCKCHIP_RGA_GET_VER		0x20
+#define DRM_ROCKCHIP_RGA_SET_CMDLIST		0x21
+#define DRM_ROCKCHIP_RGA_EXEC			0x22
+
+#define DRM_IOCTL_ROCKCHIP_RGA_GET_VER		DRM_IOWR(DRM_COMMAND_BASE + \
+	DRM_ROCKCHIP_RGA_GET_VER, struct drm_rockchip_rga_get_ver)
+
+#define DRM_IOCTL_ROCKCHIP_RGA_SET_CMDLIST	DRM_IOWR(DRM_COMMAND_BASE + \
+	DRM_ROCKCHIP_RGA_SET_CMDLIST, struct drm_rockchip_rga_set_cmdlist)
+
+#define DRM_IOCTL_ROCKCHIP_RGA_EXEC		DRM_IOWR(DRM_COMMAND_BASE + \
+	DRM_ROCKCHIP_RGA_EXEC, struct drm_rockchip_rga_exec)
+
+#endif /* _UAPI_ROCKCHIP_DRM_H */
-- 
1.9.1


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 2/4] drm: rockchip: add RGA driver support
@ 2016-03-21  9:40   ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:40 UTC (permalink / raw)
  To: linux-arm-kernel

Rockchip RGA is a separate 2D raster graphic acceleration unit. It
accelerates 2D graphics operations, such as point/line drawing, image
scaling, rotation, BitBLT, alpha blending and image blur/sharpness.

The RGA driver is based on Exynos G2D driver, it is performed by two
tasks simply.
1. Configures the rendering parameters, such as foreground color and
   coordinates data by setting the drawing context registers.
2. Start the rendering process by calling rga_exec() ioctl.

The RGA supports DMA mode as host interface. User can make command list
to reduce HOST(ARM) loads. The contents of The command list is setted to
relevant registers of RGA by DMA.

The command list is composed Header and command sets and Tail.
- Header: The number of command set(4Bytes)
- Command set: Register offset(4Bytes) + Register data(4Bytes)
- Tail: Pointer of base address of the other command list(4Bytes)

By Tail field, the G2D can process many command lists without halt at
one go.

The G2D has following the rendering pipeline.
               --->     Color Fill     --->
               |                          |
--> DMA (read) ---> Src Bitmap Process ----> Alpha/ROP ---> Format convert ---> DMA (Write)
               |                          |
               ---> Dst Bitmap Process --->

And supports various operations from the rendering pipeline.
- copy
- fast solid color fill
- rotation
- flip
- 4 operand raster operation(ROP4)
- alpha blending
- color key
- dithering
- etc

User should make the command list to data and registers needed by
operation to use. The Rockchip RGA driver only manages the command lists
received from user. Some registers needs memory base address(physical
address) of image. User doesn't know its physical address, so fills the
gem handle of that memory than address to command sets, then RGA driver
converts it to memory base address.

We adds three ioctls for Rockchip RGA.

- ioctls
DRM_ROCKCHIP_RGA_GET_VER: get the RGA hardware version
DRM_ROCKCHIP_RGA_SET_CMDLIST: set the command list from user to driver
DRM_ROCKCHIP_RGA_EXEC: execute the command lists setted to driver

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
 .../bindings/display/rockchip/rockchip-rga.txt     |  36 +
 drivers/gpu/drm/rockchip/Kconfig                   |   9 +
 drivers/gpu/drm/rockchip/Makefile                  |   1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c        |  35 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h        |   4 +
 drivers/gpu/drm/rockchip/rockchip_drm_rga.c        | 977 +++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_rga.h        | 108 +++
 include/uapi/drm/rockchip_drm.h                    |  63 ++
 8 files changed, 1232 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.h
 create mode 100644 include/uapi/drm/rockchip_drm.h

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
new file mode 100644
index 0000000..0c606cb
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
@@ -0,0 +1,36 @@
+device-tree bindings for rockchip 2D raster graphic acceleration controller (RGA)
+
+RGA is a separate 2D raster graphic acceleration unit. It accelerates 2D
+graphics operations, such as point/line drawing, image scaling, rotation,
+BitBLT, alpha blending and image blur/sharpness.
+
+Required properties:
+- compatible: value should be one of the following
+		"rockchip,rk3228-rga";
+		"rockchip,rk3288-rga";
+		"rockchip,rk3399-rga";
+
+- interrupts: RGA interrupt number.
+
+- clocks: phandle to RGA sclk/hclk/aclk clocks
+
+- clock-names: should be "aclk" "hclk" and "sclk"
+
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: should be "aclk" "hclk" and "sclk"
+
+Example:
+SoC specific DT entry:
+	rga: rga at ff680000 {
+		compatible = "rockchip,rk3399-rga";
+		reg = <0xff680000 0x10000>;
+		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "rga";
+		clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>;
+		clock-names = "aclk", "hclk", "sclk";
+
+		resets = <&cru SRST_A_RGA>, <&cru SRST_H_RGA>, <&cru SRST_RGA_CORE>;
+		reset-names = "aclk", "hclk", "sclk";
+		status = "disabled";
+	};
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 76b3362..220221b 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -16,6 +16,15 @@ config DRM_ROCKCHIP
 	  2D or 3D acceleration; acceleration is performed by other
 	  IP found on the SoC.
 
+config ROCKCHIP_DRM_RGA
+	tristate "Rockchip RGA support"
+	depends on DRM_ROCKCHIP
+	help
+	  Choose this option to enable support for Rockchip RGA.
+	  Rockchip RGA is a kind of hardware 2D accelerator, and it support
+	  solid roration, scaling, color format transform, say Y to enable its
+	  driver
+
 config ROCKCHIP_DW_HDMI
         tristate "Rockchip specific extensions for Synopsys DW HDMI"
         depends on DRM_ROCKCHIP
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index df8fbef..7de547c 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -9,5 +9,6 @@ rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
+obj-$(CONFIG_ROCKCHIP_DRM_RGA) += rockchip_drm_rga.o
 
 obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_vop_reg.o
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 4e0feb2..1638bc9 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -25,10 +25,13 @@
 #include <linux/of_graph.h>
 #include <linux/component.h>
 
+#include <drm/rockchip_drm.h>
+
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_fb.h"
 #include "rockchip_drm_fbdev.h"
 #include "rockchip_drm_gem.h"
+#include "rockchip_drm_rga.h"
 
 #define DRIVER_NAME	"rockchip"
 #define DRIVER_DESC	"RockChip Soc DRM"
@@ -277,16 +280,28 @@ EXPORT_SYMBOL_GPL(rockchip_unregister_subdrv);
 
 static int rockchip_drm_open(struct drm_device *dev, struct drm_file *file)
 {
+	struct rockchip_drm_file_private *file_priv;
 	struct drm_rockchip_subdrv *subdrv;
 	int ret = 0;
 
+	file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
+	if (!file_priv)
+		return -ENOMEM;
+
+	file->driver_priv = file_priv;
+
 	list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list) {
 		ret = subdrv->open(dev, subdrv->dev, file);
 		if (ret)
-			return ret;
+			goto err_file_priv_free;
 	}
 
 	return 0;
+
+err_file_priv_free:
+	kfree(file_priv);
+	file->driver_priv = NULL;
+	return ret;
 }
 
 static void rockchip_drm_preclose(struct drm_device *dev,
@@ -298,6 +313,12 @@ static void rockchip_drm_preclose(struct drm_device *dev,
 		subdrv->close(dev, subdrv->dev, file);
 }
 
+static void rockchip_drm_postclose(struct drm_device *dev,
+				   struct drm_file *file)
+{
+	kfree(file->driver_priv);
+}
+
 void rockchip_drm_lastclose(struct drm_device *dev)
 {
 	struct rockchip_drm_private *priv = dev->dev_private;
@@ -305,6 +326,15 @@ void rockchip_drm_lastclose(struct drm_device *dev)
 	drm_fb_helper_restore_fbdev_mode_unlocked(&priv->fbdev_helper);
 }
 
+static const struct drm_ioctl_desc rockchip_ioctls[] = {
+	DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_GET_VER, rockchip_rga_get_ver_ioctl,
+			  DRM_AUTH | DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_SET_CMDLIST, rockchip_rga_set_cmdlist_ioctl,
+			  DRM_AUTH | DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_EXEC, rockchip_rga_exec_ioctl,
+			  DRM_AUTH | DRM_RENDER_ALLOW),
+};
+
 static const struct file_operations rockchip_drm_driver_fops = {
 	.owner = THIS_MODULE,
 	.open = drm_open,
@@ -330,6 +360,7 @@ static struct drm_driver rockchip_drm_driver = {
 	.unload			= rockchip_drm_unload,
 	.open			= rockchip_drm_open,
 	.preclose		= rockchip_drm_preclose,
+	.postclose		= rockchip_drm_postclose,
 	.lastclose		= rockchip_drm_lastclose,
 	.get_vblank_counter	= drm_vblank_no_hw_counter,
 	.enable_vblank		= rockchip_drm_crtc_enable_vblank,
@@ -347,6 +378,8 @@ static struct drm_driver rockchip_drm_driver = {
 	.gem_prime_vmap		= rockchip_gem_prime_vmap,
 	.gem_prime_vunmap	= rockchip_gem_prime_vunmap,
 	.gem_prime_mmap		= rockchip_gem_mmap_buf,
+	.ioctls			= rockchip_ioctls,
+	.num_ioctls		= ARRAY_SIZE(rockchip_ioctls),
 	.fops			= &rockchip_drm_driver_fops,
 	.name	= DRIVER_NAME,
 	.desc	= DRIVER_DESC,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 5ea5fcb..ea30ba6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -53,6 +53,10 @@ struct drm_rockchip_subdrv {
 		      struct drm_file *file);
 };
 
+struct rockchip_drm_file_private {
+	struct rockchip_drm_rga_private *rga_priv;
+};
+
 struct rockchip_atomic_commit {
 	struct work_struct	work;
 	struct drm_atomic_state *state;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_rga.c b/drivers/gpu/drm/rockchip/rockchip_drm_rga.c
new file mode 100644
index 0000000..4202121
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_rga.c
@@ -0,0 +1,977 @@
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Yakir Yang <ykk@rock-chips.com>
+ *
+ * based on exynos_drm_g2d.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <drm/drmP.h>
+#include <drm/rockchip_drm.h>
+
+#include "rockchip_drm_drv.h"
+#include "rockchip_drm_rga.h"
+
+#define RGA_MODE_BASE_REG		0x0100
+#define RGA_MODE_MAX_REG		0x017C
+
+#define RGA_SYS_CTRL			0x0000
+#define RGA_CMD_CTRL			0x0004
+#define RGA_CMD_BASE			0x0008
+#define RGA_INT				0x0010
+#define RGA_MMU_CTRL0			0x0014
+#define RGA_VERSION_INFO		0x0028
+
+#define RGA_SRC_Y_RGB_BASE_ADDR		0x0108
+#define RGA_SRC_CB_BASE_ADDR		0x010C
+#define RGA_SRC_CR_BASE_ADDR		0x0110
+#define RGA_SRC1_RGB_BASE_ADDR		0x0114
+#define RGA_DST_Y_RGB_BASE_ADDR		0x013C
+#define RGA_DST_CB_BASE_ADDR		0x0140
+#define RGA_DST_CR_BASE_ADDR		0x014C
+#define RGA_MMU_CTRL1			0x016C
+#define RGA_MMU_SRC_BASE		0x0170
+#define RGA_MMU_SRC1_BASE		0x0174
+#define RGA_MMU_DST_BASE		0x0178
+
+static void rga_dma_flush_range(void *ptr, int size)
+{
+#ifdef CONFIG_ARM
+	dmac_flush_range(ptr, ptr + size);
+	outer_flush_range(virt_to_phys(ptr), virt_to_phys(ptr + size));
+#elif CONFIG_ARM64
+	__dma_flush_range(ptr, ptr + size);
+#endif
+}
+
+static inline void rga_write(struct rockchip_rga *rga, u32 reg, u32 value)
+{
+	writel(value, rga->regs + reg);
+}
+
+static inline u32 rga_read(struct rockchip_rga *rga, u32 reg)
+{
+	return readl(rga->regs + reg);
+}
+
+static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
+{
+	u32 temp = rga_read(rga, reg) & ~(mask);
+
+	temp |= val & mask;
+	rga_write(rga, reg, temp);
+}
+
+static int rga_enable_clocks(struct rockchip_rga *rga)
+{
+	int ret;
+
+	ret = clk_prepare_enable(rga->sclk);
+	if (ret) {
+		dev_err(rga->dev, "Cannot enable rga sclk: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(rga->aclk);
+	if (ret) {
+		dev_err(rga->dev, "Cannot enable rga aclk: %d\n", ret);
+		goto err_disable_sclk;
+	}
+
+	ret = clk_prepare_enable(rga->hclk);
+	if (ret) {
+		dev_err(rga->dev, "Cannot enable rga hclk: %d\n", ret);
+		goto err_disable_aclk;
+	}
+
+	return 0;
+
+err_disable_sclk:
+	clk_disable_unprepare(rga->sclk);
+err_disable_aclk:
+	clk_disable_unprepare(rga->aclk);
+
+	return ret;
+}
+
+static void rga_disable_clocks(struct rockchip_rga *rga)
+{
+	clk_disable_unprepare(rga->sclk);
+	clk_disable_unprepare(rga->hclk);
+	clk_disable_unprepare(rga->aclk);
+}
+
+static void rga_init_cmdlist(struct rockchip_rga *rga)
+{
+	struct rga_cmdlist_node *node;
+	int nr;
+
+	node = rga->cmdlist_node;
+
+	for (nr = 0; nr < ARRAY_SIZE(rga->cmdlist_node); nr++)
+		list_add_tail(&node[nr].list, &rga->free_cmdlist);
+}
+
+static int rga_alloc_dma_buf_for_cmdlist(struct rga_runqueue_node *runqueue)
+{
+	struct list_head *run_cmdlist = &runqueue->run_cmdlist;
+	struct device *dev = runqueue->dev;
+	struct dma_attrs cmdlist_dma_attrs;
+	struct rga_cmdlist_node *node;
+	void *cmdlist_pool_virt;
+	dma_addr_t cmdlist_pool;
+	int cmdlist_cnt = 0;
+	int count = 0;
+
+	list_for_each_entry(node, run_cmdlist, list)
+		cmdlist_cnt++;
+
+	init_dma_attrs(&cmdlist_dma_attrs);
+	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &runqueue->cmdlist_dma_attrs);
+
+	cmdlist_pool_virt = dma_alloc_attrs(dev, cmdlist_cnt * RGA_CMDLIST_SIZE,
+					    &cmdlist_pool, GFP_KERNEL,
+					    &cmdlist_dma_attrs);
+	if (!cmdlist_pool_virt) {
+		dev_err(dev, "failed to allocate cmdlist dma memory\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * Fill in the RGA operation registers from cmdlist command buffer,
+	 * and also filled in the MMU TLB base information.
+	 */
+	list_for_each_entry(node, run_cmdlist, list) {
+		struct rga_cmdlist *cmdlist = &node->cmdlist;
+		unsigned int mmu_ctrl = 0;
+		unsigned int *dest;
+		unsigned int reg;
+		int i;
+
+		dest = cmdlist_pool_virt + RGA_CMDLIST_SIZE * 4 * count++;
+
+		for (i = 0; i < cmdlist->last / 2; i++) {
+			reg = (node->cmdlist.data[2 * i] - RGA_MODE_BASE_REG);
+			if (reg > RGA_MODE_BASE_REG)
+				continue;
+			dest[reg << 2] = cmdlist->data[2 * i + 1];
+		}
+
+		if (cmdlist->src_mmu_pages) {
+			reg = RGA_MMU_SRC_BASE - RGA_MODE_BASE_REG;
+			dest[reg << 2] = virt_to_phys(cmdlist->src_mmu_pages) >> 4;
+			mmu_ctrl |= 0x7;
+		}
+
+		if (cmdlist->dst_mmu_pages) {
+			reg = RGA_MMU_DST_BASE - RGA_MODE_BASE_REG;
+			dest[reg << 2] = virt_to_phys(cmdlist->dst_mmu_pages) >> 4;
+			mmu_ctrl |= 0x7 << 8;
+		}
+
+		if (cmdlist->src1_mmu_pages) {
+			reg = RGA_MMU_SRC1_BASE - RGA_MODE_BASE_REG;
+			dest[reg << 2] = virt_to_phys(cmdlist->src1_mmu_pages) >> 4;
+			mmu_ctrl |= 0x7 << 4;
+		}
+
+		reg = RGA_MMU_CTRL1 - RGA_MODE_BASE_REG;
+		dest[reg << 2] = mmu_ctrl;
+	}
+
+	rga_dma_flush_range(cmdlist_pool_virt, cmdlist_cnt * RGA_CMDLIST_SIZE);
+
+	runqueue->cmdlist_dma_attrs = cmdlist_dma_attrs;
+	runqueue->cmdlist_pool_virt = cmdlist_pool_virt;
+	runqueue->cmdlist_pool = cmdlist_pool;
+	runqueue->cmdlist_cnt = cmdlist_cnt;
+
+	return 0;
+}
+
+static int rga_check_reg_offset(struct device *dev,
+				struct rga_cmdlist_node *node)
+{
+	struct rga_cmdlist *cmdlist = &node->cmdlist;
+	int index;
+	int reg;
+	int i;
+
+	for (i = 0; i < cmdlist->last / 2; i++) {
+		index = cmdlist->last - 2 * (i + 1);
+		reg = cmdlist->data[index];
+
+		switch (reg) {
+		case RGA_BUF_TYPE_GEMFD | RGA_DST_Y_RGB_BASE_ADDR:
+		case RGA_BUF_TYPE_GEMFD | RGA_SRC_Y_RGB_BASE_ADDR:
+			break;
+
+		case RGA_BUF_TYPE_USERPTR | RGA_DST_Y_RGB_BASE_ADDR:
+		case RGA_BUF_TYPE_USERPTR | RGA_SRC_Y_RGB_BASE_ADDR:
+			goto err;
+
+		default:
+			if (reg < RGA_MODE_BASE_REG || reg > RGA_MODE_MAX_REG)
+				goto err;
+
+			if (reg % 4)
+				goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	dev_err(dev, "Bad register offset: 0x%lx\n", cmdlist->data[index]);
+	return -EINVAL;
+}
+
+static struct dma_buf_attachment *
+rga_gem_buf_to_pages(struct rockchip_rga *rga, void **mmu_pages, int fd)
+{
+	struct dma_buf_attachment *attach;
+	struct dma_buf *dmabuf;
+	struct sg_table *sgt;
+	struct scatterlist *sgl;
+	unsigned int mapped_size = 0;
+	unsigned int address;
+	unsigned int len;
+	unsigned int i, p;
+	unsigned int *pages;
+	int ret;
+
+	dmabuf = dma_buf_get(fd);
+	if (IS_ERR(dmabuf)) {
+		dev_err(rga->dev, "Failed to get dma_buf with fd %d\n", fd);
+		return ERR_PTR(-EINVAL);
+	}
+
+	attach = dma_buf_attach(dmabuf, rga->dev);
+	if (IS_ERR(attach)) {
+		dev_err(rga->dev, "Failed to attach dma_buf\n");
+		ret = PTR_ERR(attach);
+		goto failed_attach;
+	}
+
+	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+	if (IS_ERR(sgt)) {
+		dev_err(rga->dev, "Failed to map dma_buf attachment\n");
+		ret = PTR_ERR(sgt);
+		goto failed_detach;
+	}
+
+	/*
+	 * Alloc (2^3 * 4K) = 32K byte for storing pages, those space could
+	 * cover 32K * 4K = 128M ram address.
+	 */
+	pages = (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
+
+	for_each_sg(sgt->sgl, sgl, sgt->nents, i) {
+		len = sg_dma_len(sgl) >> PAGE_SHIFT;
+		address = sg_phys(sgl);
+
+		for (p = 0; p < len; p++) {
+			dma_addr_t phys = address + (p << PAGE_SHIFT);
+			void *virt = phys_to_virt(phys);
+
+			rga_dma_flush_range(virt, 4 * 1024);
+			pages[mapped_size + p] = phys;
+		}
+
+		mapped_size += len;
+	}
+
+	rga_dma_flush_range(pages, 32 * 1024);
+
+	*mmu_pages = pages;
+
+	dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+
+	return attach;
+
+failed_detach:
+	dma_buf_detach(dmabuf, attach);
+failed_attach:
+	dma_buf_put(dmabuf);
+
+	return ERR_PTR(ret);
+}
+
+static int rga_map_cmdlist_gem(struct rockchip_rga *rga,
+			       struct rga_cmdlist_node *node,
+			       struct drm_device *drm_dev,
+			       struct drm_file *file)
+{
+	struct rga_cmdlist *cmdlist = &node->cmdlist;
+	struct dma_buf_attachment *attach;
+	void *mmu_pages;
+	int fd;
+	int i;
+
+	for (i = 0; i < cmdlist->last / 2; i++) {
+		int index = cmdlist->last - 2 * (i + 1);
+
+		switch (cmdlist->data[index]) {
+		case RGA_SRC_Y_RGB_BASE_ADDR | RGA_BUF_TYPE_GEMFD:
+			fd = cmdlist->data[index + 1];
+			attach = rga_gem_buf_to_pages(rga, &mmu_pages, fd);
+
+			cmdlist->src_attach = attach;
+			cmdlist->src_mmu_pages = mmu_pages;
+			break;
+
+		case RGA_DST_Y_RGB_BASE_ADDR | RGA_BUF_TYPE_GEMFD:
+			fd = cmdlist->data[index + 1];
+			attach = rga_gem_buf_to_pages(rga, &mmu_pages, fd);
+
+			cmdlist->dst_attach = attach;
+			cmdlist->dst_mmu_pages = mmu_pages;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static void rga_unmap_cmdlist_gem(struct rockchip_rga *rga,
+				  struct rga_cmdlist_node *node)
+{
+	struct dma_buf_attachment *attach;
+	struct dma_buf *dma_buf;
+
+	attach = node->cmdlist.src_attach;
+	if (attach) {
+		dma_buf = attach->dmabuf;
+		dma_buf_detach(dma_buf, attach);
+		dma_buf_put(dma_buf);
+	}
+	node->cmdlist.src_attach = NULL;
+
+	attach = node->cmdlist.dst_attach;
+	if (attach) {
+		dma_buf = attach->dmabuf;
+		dma_buf_detach(dma_buf, attach);
+		dma_buf_put(dma_buf);
+	}
+	node->cmdlist.dst_attach = NULL;
+
+	if (node->cmdlist.src_mmu_pages)
+		free_pages((unsigned long)node->cmdlist.src_mmu_pages, 3);
+	node->cmdlist.src_mmu_pages = NULL;
+
+	if (node->cmdlist.src1_mmu_pages)
+		free_pages((unsigned long)node->cmdlist.src1_mmu_pages, 3);
+	node->cmdlist.src1_mmu_pages = NULL;
+
+	if (node->cmdlist.dst_mmu_pages)
+		free_pages((unsigned long)node->cmdlist.dst_mmu_pages, 3);
+	node->cmdlist.dst_mmu_pages = NULL;
+}
+
+static void rga_cmd_start(struct rockchip_rga *rga,
+			  struct rga_runqueue_node *runqueue)
+{
+	int ret;
+
+	ret = pm_runtime_get_sync(rga->dev);
+	if (ret < 0)
+		return;
+
+	rga_write(rga, RGA_SYS_CTRL, 0x00);
+
+	rga_write(rga, RGA_CMD_BASE, runqueue->cmdlist_pool);
+
+	rga_write(rga, RGA_SYS_CTRL, 0x22);
+
+	rga_write(rga, RGA_INT, 0x600);
+
+	rga_write(rga, RGA_CMD_CTRL, ((runqueue->cmdlist_cnt - 1) << 3) | 0x1);
+}
+
+static void rga_free_runqueue_node(struct rockchip_rga *rga,
+				   struct rga_runqueue_node *runqueue)
+{
+	struct rga_cmdlist_node *node;
+
+	if (!runqueue)
+		return;
+
+	if (runqueue->cmdlist_pool_virt && runqueue->cmdlist_pool)
+		dma_free_attrs(rga->dev, runqueue->cmdlist_cnt * RGA_CMDLIST_SIZE,
+			       runqueue->cmdlist_pool_virt,
+			       runqueue->cmdlist_pool,
+			       &runqueue->cmdlist_dma_attrs);
+
+	mutex_lock(&rga->cmdlist_mutex);
+	/*
+	 * commands in run_cmdlist have been completed so unmap all gem
+	 * objects in each command node so that they are unreferenced.
+	 */
+	list_for_each_entry(node, &runqueue->run_cmdlist, list)
+		rga_unmap_cmdlist_gem(rga, node);
+	list_splice_tail_init(&runqueue->run_cmdlist, &rga->free_cmdlist);
+	mutex_unlock(&rga->cmdlist_mutex);
+
+	kmem_cache_free(rga->runqueue_slab, runqueue);
+}
+
+static struct rga_runqueue_node *rga_get_runqueue(struct rockchip_rga *rga)
+{
+	struct rga_runqueue_node *runqueue;
+
+	if (list_empty(&rga->runqueue_list))
+		return NULL;
+
+	runqueue = list_first_entry(&rga->runqueue_list,
+				    struct rga_runqueue_node, list);
+	list_del_init(&runqueue->list);
+
+	return runqueue;
+}
+
+static void rga_exec_runqueue(struct rockchip_rga *rga)
+{
+	rga->runqueue_node = rga_get_runqueue(rga);
+	if (rga->runqueue_node)
+		rga_cmd_start(rga, rga->runqueue_node);
+}
+
+static struct rga_cmdlist_node *rga_get_cmdlist(struct rockchip_rga *rga)
+{
+	struct rga_cmdlist_node *node;
+	struct device *dev = rga->dev;
+
+	mutex_lock(&rga->cmdlist_mutex);
+	if (list_empty(&rga->free_cmdlist)) {
+		dev_err(dev, "there is no free cmdlist\n");
+		mutex_unlock(&rga->cmdlist_mutex);
+		return NULL;
+	}
+
+	node = list_first_entry(&rga->free_cmdlist,
+				struct rga_cmdlist_node, list);
+	list_del_init(&node->list);
+	mutex_unlock(&rga->cmdlist_mutex);
+
+	return node;
+}
+
+static void rga_add_cmdlist_to_inuse(struct rockchip_drm_rga_private *rga_priv,
+				     struct rga_cmdlist_node *node)
+{
+	struct rga_cmdlist_node *lnode;
+
+	if (list_empty(&rga_priv->inuse_cmdlist))
+		goto add_to_list;
+
+	/* this links to base address of new cmdlist */
+	lnode = list_entry(rga_priv->inuse_cmdlist.prev,
+			   struct rga_cmdlist_node, list);
+
+add_to_list:
+	list_add_tail(&node->list, &rga_priv->inuse_cmdlist);
+}
+
+/*
+ * IOCRL functions for userspace to get RGA version.
+ */
+int rockchip_rga_get_ver_ioctl(struct drm_device *drm_dev, void *data,
+			       struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
+	struct drm_rockchip_rga_get_ver *ver = data;
+	struct rockchip_rga *rga;
+	struct device *dev;
+
+	if (!rga_priv)
+		return -ENODEV;
+
+	dev = rga_priv->dev;
+	if (!dev)
+		return -ENODEV;
+
+	rga = dev_get_drvdata(dev);
+	if (!rga)
+		return -EFAULT;
+
+	ver->major = rga->version.major;
+	ver->minor = rga->version.minor;
+
+	return 0;
+}
+
+/*
+ * IOCRL functions for userspace to send an RGA request.
+ */
+int rockchip_rga_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
+				   struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
+	struct drm_rockchip_rga_set_cmdlist *req = data;
+	struct rga_cmdlist_node *node;
+	struct rga_cmdlist *cmdlist;
+	struct rockchip_rga *rga;
+	int ret;
+
+	if (!rga_priv)
+		return -ENODEV;
+
+	if (!rga_priv->dev)
+		return -ENODEV;
+
+	rga = dev_get_drvdata(rga_priv->dev);
+	if (!rga)
+		return -EFAULT;
+
+	node = rga_get_cmdlist(rga);
+	if (!node)
+		return -ENOMEM;
+
+	cmdlist = &node->cmdlist;
+	cmdlist->last = 0;
+
+	if (req->cmd_nr > RGA_CMDLIST_SIZE || req->cmd_buf_nr > RGA_CMDBUF_SIZE) {
+		dev_err(rga->dev, "cmdlist size is too big\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Copy the command / buffer registers setting from userspace, each
+	 * command have two integer, one for register offset, another for
+	 * register value.
+	 */
+	if (copy_from_user((void *)cmdlist->data, (const void __user *)req->cmd,
+			   sizeof(struct drm_rockchip_rga_cmd) * req->cmd_nr))
+		return -EFAULT;
+	cmdlist->last += req->cmd_nr * 2;
+
+	if (copy_from_user((void *)cmdlist->data + cmdlist->last,
+			   (const void __user *)req->cmd_buf,
+			   sizeof(struct drm_rockchip_rga_cmd) * req->cmd_buf_nr))
+		return -EFAULT;
+	cmdlist->last += req->cmd_buf_nr * 2;
+
+	/*
+	 * Check the userspace command registers, and mapping the framebuffer,
+	 * create the RGA mmu pages or get the framebuffer dma address.
+	 */
+	ret = rga_check_reg_offset(rga->dev, node);
+	if (ret < 0)
+		return ret;
+
+	ret = rga_map_cmdlist_gem(rga, node, drm_dev, file);
+	if (ret < 0)
+		return ret;
+
+	rga_add_cmdlist_to_inuse(rga_priv, node);
+
+	return 0;
+}
+
+/*
+ * IOCRL functions for userspace to start RGA transform.
+ */
+int rockchip_rga_exec_ioctl(struct drm_device *drm_dev, void *data,
+			    struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
+	struct rga_runqueue_node *runqueue;
+	struct rockchip_rga *rga;
+	struct device *dev;
+	int ret;
+
+	if (!rga_priv)
+		return -ENODEV;
+
+	dev = rga_priv->dev;
+	if (!dev)
+		return -ENODEV;
+
+	rga = dev_get_drvdata(dev);
+	if (!rga)
+		return -EFAULT;
+
+	runqueue = kmem_cache_alloc(rga->runqueue_slab, GFP_KERNEL);
+	if (!runqueue) {
+		dev_err(rga->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	runqueue->dev = rga->dev;
+
+	init_completion(&runqueue->complete);
+
+	INIT_LIST_HEAD(&runqueue->run_cmdlist);
+
+	list_splice_init(&rga_priv->inuse_cmdlist, &runqueue->run_cmdlist);
+
+	if (list_empty(&runqueue->run_cmdlist)) {
+		dev_err(rga->dev, "there is no inuse cmdlist\n");
+		kmem_cache_free(rga->runqueue_slab, runqueue);
+		return -EPERM;
+	}
+
+	ret = rga_alloc_dma_buf_for_cmdlist(runqueue);
+	if (ret < 0) {
+		dev_err(rga->dev, "cmdlist init failed\n");
+		return ret;
+	}
+
+	mutex_lock(&rga->runqueue_mutex);
+	runqueue->pid = current->pid;
+	runqueue->file = file;
+	list_add_tail(&runqueue->list, &rga->runqueue_list);
+	if (!rga->runqueue_node)
+		rga_exec_runqueue(rga);
+	mutex_unlock(&rga->runqueue_mutex);
+
+	wait_for_completion(&runqueue->complete);
+	rga_free_runqueue_node(rga, runqueue);
+
+	return 0;
+}
+
+static int rockchip_rga_open(struct drm_device *drm_dev, struct device *dev,
+			     struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv;
+
+	rga_priv = kzalloc(sizeof(*rga_priv), GFP_KERNEL);
+	if (!rga_priv)
+		return -ENOMEM;
+
+	rga_priv->dev = dev;
+	file_priv->rga_priv = rga_priv;
+
+	INIT_LIST_HEAD(&rga_priv->inuse_cmdlist);
+
+	return 0;
+}
+
+static void rockchip_rga_close(struct drm_device *drm_dev, struct device *dev,
+			       struct drm_file *file)
+{
+	struct rockchip_drm_file_private *file_priv = file->driver_priv;
+	struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
+	struct rga_cmdlist_node *node, *n;
+	struct rockchip_rga *rga;
+
+	if (!dev)
+		return;
+
+	rga = dev_get_drvdata(dev);
+	if (!rga)
+		return;
+
+	mutex_lock(&rga->cmdlist_mutex);
+	list_for_each_entry_safe(node, n, &rga_priv->inuse_cmdlist, list) {
+		/*
+		 * unmap all gem objects not completed.
+		 *
+		 * P.S. if current process was terminated forcely then
+		 * there may be some commands in inuse_cmdlist so unmap
+		 * them.
+		 */
+		rga_unmap_cmdlist_gem(rga, node);
+		list_move_tail(&node->list, &rga->free_cmdlist);
+	}
+	mutex_unlock(&rga->cmdlist_mutex);
+
+	kfree(file_priv->rga_priv);
+}
+
+static void rga_runqueue_worker(struct work_struct *work)
+{
+	struct rockchip_rga *rga = container_of(work, struct rockchip_rga,
+					    runqueue_work);
+
+	mutex_lock(&rga->runqueue_mutex);
+	pm_runtime_put_sync(rga->dev);
+
+	complete(&rga->runqueue_node->complete);
+
+	if (rga->suspended)
+		rga->runqueue_node = NULL;
+	else
+		rga_exec_runqueue(rga);
+
+	mutex_unlock(&rga->runqueue_mutex);
+}
+
+static irqreturn_t rga_irq_handler(int irq, void *dev_id)
+{
+	struct rockchip_rga *rga = dev_id;
+	int intr;
+
+	intr = rga_read(rga, RGA_INT) & 0xf;
+
+	rga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
+
+	if (intr & 0x04)
+		queue_work(rga->rga_workq, &rga->runqueue_work);
+
+	return IRQ_HANDLED;
+}
+
+static int rga_parse_dt(struct rockchip_rga *rga)
+{
+	struct reset_control *sclk_rst, *aclk_rst, *hclk_rst;
+
+	sclk_rst = devm_reset_control_get(rga->dev, "sclk");
+	if (IS_ERR(sclk_rst)) {
+		dev_err(rga->dev, "failed to get sclk reset controller\n");
+		return PTR_ERR(sclk_rst);
+	}
+
+	aclk_rst = devm_reset_control_get(rga->dev, "aclk");
+	if (IS_ERR(aclk_rst)) {
+		dev_err(rga->dev, "failed to get aclk reset controller\n");
+		return PTR_ERR(aclk_rst);
+	}
+
+	hclk_rst = devm_reset_control_get(rga->dev, "hclk");
+	if (IS_ERR(hclk_rst)) {
+		dev_err(rga->dev, "failed to get hclk reset controller\n");
+		return PTR_ERR(hclk_rst);
+	}
+
+	reset_control_assert(sclk_rst);
+	usleep_range(10, 20);
+	reset_control_deassert(sclk_rst);
+
+	reset_control_assert(aclk_rst);
+	usleep_range(10, 20);
+	reset_control_deassert(aclk_rst);
+
+	reset_control_assert(hclk_rst);
+	usleep_range(10, 20);
+	reset_control_deassert(hclk_rst);
+
+	rga->sclk = devm_clk_get(rga->dev, "sclk");
+	if (IS_ERR(rga->sclk)) {
+		dev_err(rga->dev, "failed to get sclk clock\n");
+		return PTR_ERR(rga->sclk);
+	}
+
+	rga->aclk = devm_clk_get(rga->dev, "aclk");
+	if (IS_ERR(rga->aclk)) {
+		dev_err(rga->dev, "failed to get aclk clock\n");
+		return PTR_ERR(rga->aclk);
+	}
+
+	rga->hclk = devm_clk_get(rga->dev, "hclk");
+	if (IS_ERR(rga->hclk)) {
+		dev_err(rga->dev, "failed to get hclk clock\n");
+		return PTR_ERR(rga->hclk);
+	}
+
+	return rga_enable_clocks(rga);
+}
+
+static const struct of_device_id rockchip_rga_dt_ids[] = {
+	{ .compatible = "rockchip,rk3288-rga", },
+	{ .compatible = "rockchip,rk3228-rga", },
+	{ .compatible = "rockchip,rk3399-rga", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, rockchip_rga_dt_ids);
+
+static int rga_probe(struct platform_device *pdev)
+{
+	struct drm_rockchip_subdrv *subdrv;
+	struct rockchip_rga *rga;
+	struct resource *iores;
+	int irq;
+	int ret;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	rga = devm_kzalloc(&pdev->dev, sizeof(*rga), GFP_KERNEL);
+	if (!rga)
+		return -ENOMEM;
+
+	rga->dev = &pdev->dev;
+
+	rga->runqueue_slab = kmem_cache_create("rga_runqueue_slab",
+					       sizeof(struct rga_runqueue_node),
+					       0, 0, NULL);
+	if (!rga->runqueue_slab)
+		return -ENOMEM;
+
+	rga->rga_workq = create_singlethread_workqueue("rga");
+	if (!rga->rga_workq) {
+		dev_err(rga->dev, "failed to create workqueue\n");
+		goto err_destroy_slab;
+	}
+
+	INIT_WORK(&rga->runqueue_work, rga_runqueue_worker);
+	INIT_LIST_HEAD(&rga->runqueue_list);
+	mutex_init(&rga->runqueue_mutex);
+
+	INIT_LIST_HEAD(&rga->free_cmdlist);
+	mutex_init(&rga->cmdlist_mutex);
+
+	rga_init_cmdlist(rga);
+
+	ret = rga_parse_dt(rga);
+	if (ret) {
+		dev_err(rga->dev, "Unable to parse OF data\n");
+		goto err_destroy_workqueue;
+	}
+
+	pm_runtime_enable(rga->dev);
+
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	rga->regs = devm_ioremap_resource(rga->dev, iores);
+	if (IS_ERR(rga->regs)) {
+		ret = PTR_ERR(rga->regs);
+		goto err_put_clk;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(rga->dev, "failed to get irq\n");
+		ret = irq;
+		goto err_put_clk;
+	}
+
+	ret = devm_request_irq(rga->dev, irq, rga_irq_handler, 0,
+			       dev_name(rga->dev), rga);
+	if (ret < 0) {
+		dev_err(rga->dev, "failed to request irq\n");
+		goto err_put_clk;
+	}
+
+	platform_set_drvdata(pdev, rga);
+
+	rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
+	rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
+
+	subdrv = &rga->subdrv;
+	subdrv->dev = rga->dev;
+	subdrv->open = rockchip_rga_open;
+	subdrv->close = rockchip_rga_close;
+
+	rockchip_register_subdrv(subdrv);
+
+	return 0;
+
+err_put_clk:
+	pm_runtime_disable(rga->dev);
+err_destroy_workqueue:
+	destroy_workqueue(rga->rga_workq);
+err_destroy_slab:
+	kmem_cache_destroy(rga->runqueue_slab);
+
+	return ret;
+}
+
+static int rga_remove(struct platform_device *pdev)
+{
+	struct rockchip_rga *rga = platform_get_drvdata(pdev);
+
+	cancel_work_sync(&rga->runqueue_work);
+
+	while (rga->runqueue_node) {
+		rga_free_runqueue_node(rga, rga->runqueue_node);
+		rga->runqueue_node = rga_get_runqueue(rga);
+	}
+
+	rockchip_unregister_subdrv(&rga->subdrv);
+
+	return 0;
+}
+
+static int rga_suspend(struct device *dev)
+{
+	struct rockchip_rga *rga = dev_get_drvdata(dev);
+
+	mutex_lock(&rga->runqueue_mutex);
+	rga->suspended = true;
+	mutex_unlock(&rga->runqueue_mutex);
+
+	flush_work(&rga->runqueue_work);
+
+	return 0;
+}
+
+static int rga_resume(struct device *dev)
+{
+	struct rockchip_rga *rga = dev_get_drvdata(dev);
+
+	rga->suspended = false;
+	rga_exec_runqueue(rga);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int rga_runtime_suspend(struct device *dev)
+{
+	struct rockchip_rga *rga = dev_get_drvdata(dev);
+
+	rga_disable_clocks(rga);
+
+	return 0;
+}
+
+static int rga_runtime_resume(struct device *dev)
+{
+	struct rockchip_rga *rga = dev_get_drvdata(dev);
+
+	return rga_enable_clocks(rga);
+}
+#endif
+
+static const struct dev_pm_ops rga_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(rga_suspend, rga_resume)
+	SET_RUNTIME_PM_OPS(rga_runtime_suspend,
+			   rga_runtime_resume, NULL)
+};
+
+static struct platform_driver rga_pltfm_driver = {
+	.probe  = rga_probe,
+	.remove = rga_remove,
+	.driver = {
+		.name = "rockchip-rga",
+		.pm = &rga_pm,
+		.of_match_table = rockchip_rga_dt_ids,
+	},
+};
+
+module_platform_driver(rga_pltfm_driver);
+
+MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip RGA Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:rockchip-rga");
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_rga.h b/drivers/gpu/drm/rockchip/rockchip_drm_rga.h
new file mode 100644
index 0000000..4a8839a
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_rga.h
@@ -0,0 +1,108 @@
+#ifndef __ROCKCHIP_DRM_RGA__
+#define __ROCKCHIP_DRM_RGA__
+
+#define RGA_CMDBUF_SIZE			14
+#define RGA_CMDLIST_SIZE		0x20
+#define RGA_CMDLIST_NUM			64
+
+/* cmdlist data structure */
+struct rga_cmdlist {
+	u32		head;
+	unsigned long	data[RGA_CMDLIST_SIZE * 2];
+	u32		last;	/* last data offset */
+	void		*src_mmu_pages;
+	void		*dst_mmu_pages;
+	void		*src1_mmu_pages;
+	struct dma_buf_attachment *src_attach;
+	struct dma_buf_attachment *dst_attach;
+};
+
+struct rga_cmdlist_node {
+	struct list_head	list;
+	struct rga_cmdlist	cmdlist;
+};
+
+struct rga_runqueue_node {
+	struct list_head	list;
+
+	struct device		*dev;
+	pid_t			pid;
+	struct drm_file		*file;
+	struct completion	complete;
+
+	struct list_head	run_cmdlist;
+
+	int			cmdlist_cnt;
+	void			*cmdlist_pool_virt;
+	dma_addr_t		cmdlist_pool;
+	struct dma_attrs	cmdlist_dma_attrs;
+};
+
+struct rockchip_rga_version {
+	__u32			major;
+	__u32			minor;
+};
+
+struct rockchip_rga {
+	struct drm_device	*drm_dev;
+	struct device		*dev;
+	struct regmap		*grf;
+	void __iomem		*regs;
+	struct clk		*sclk;
+	struct clk		*aclk;
+	struct clk		*hclk;
+
+	bool				suspended;
+	struct rockchip_rga_version	version;
+	struct drm_rockchip_subdrv	subdrv;
+	struct workqueue_struct		*rga_workq;
+	struct work_struct		runqueue_work;
+
+	/* rga command list pool */
+	struct rga_cmdlist_node		cmdlist_node[RGA_CMDLIST_NUM];
+	struct mutex			cmdlist_mutex;
+
+	struct list_head		free_cmdlist;
+
+	/* rga runqueue */
+	struct rga_runqueue_node	*runqueue_node;
+	struct list_head		runqueue_list;
+	struct mutex			runqueue_mutex;
+	struct kmem_cache		*runqueue_slab;
+};
+
+struct rockchip_drm_rga_private {
+	struct device		*dev;
+	struct list_head	inuse_cmdlist;
+	struct list_head	userptr_list;
+};
+
+#ifdef CONFIG_ROCKCHIP_DRM_RGA
+int rockchip_rga_get_ver_ioctl(struct drm_device *dev, void *data,
+			       struct drm_file *file_priv);
+int rockchip_rga_set_cmdlist_ioctl(struct drm_device *dev, void *data,
+				   struct drm_file *file_priv);
+int rockchip_rga_exec_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv);
+#else
+static inline int rockchip_rga_get_ver_ioctl(struct drm_device *dev, void *data,
+					     struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int rockchip_rga_set_cmdlist_ioctl(struct drm_device *dev,
+						 void *data,
+						 struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int rockchip_rga_exec_ioctl(struct drm_device *dev, void *data,
+					  struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif /* __ROCKCHIP_DRM_RGA__ */
diff --git a/include/uapi/drm/rockchip_drm.h b/include/uapi/drm/rockchip_drm.h
new file mode 100644
index 0000000..2e3e240
--- /dev/null
+++ b/include/uapi/drm/rockchip_drm.h
@@ -0,0 +1,63 @@
+/* rockchip_drm.h
+ *
+ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ * Authors:
+ *	Yakir Yang <ykk@rock-chips.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _UAPI_ROCKCHIP_DRM_H_
+#define _UAPI_ROCKCHIP_DRM_H_
+
+#include <drm/drm.h>
+
+struct drm_rockchip_rga_get_ver {
+	__u32   major;
+	__u32   minor;
+};
+
+struct drm_rockchip_rga_cmd {
+	__u32   offset;
+	__u32   data;
+};
+
+enum drm_rockchip_rga_buf_type {
+	RGA_BUF_TYPE_USERPTR = 1 << 31,
+	RGA_BUF_TYPE_GEMFD   = 1 << 30,
+};
+
+struct drm_rockchip_rga_userptr {
+	unsigned long userptr;
+	unsigned long size;
+};
+
+struct drm_rockchip_rga_set_cmdlist {
+	__u64		cmd;
+	__u64		cmd_buf;
+	__u32		cmd_nr;
+	__u32		cmd_buf_nr;
+	__u64		user_data;
+};
+
+struct drm_rockchip_rga_exec {
+	__u64		async;
+};
+
+#define DRM_ROCKCHIP_RGA_GET_VER		0x20
+#define DRM_ROCKCHIP_RGA_SET_CMDLIST		0x21
+#define DRM_ROCKCHIP_RGA_EXEC			0x22
+
+#define DRM_IOCTL_ROCKCHIP_RGA_GET_VER		DRM_IOWR(DRM_COMMAND_BASE + \
+	DRM_ROCKCHIP_RGA_GET_VER, struct drm_rockchip_rga_get_ver)
+
+#define DRM_IOCTL_ROCKCHIP_RGA_SET_CMDLIST	DRM_IOWR(DRM_COMMAND_BASE + \
+	DRM_ROCKCHIP_RGA_SET_CMDLIST, struct drm_rockchip_rga_set_cmdlist)
+
+#define DRM_IOCTL_ROCKCHIP_RGA_EXEC		DRM_IOWR(DRM_COMMAND_BASE + \
+	DRM_ROCKCHIP_RGA_EXEC, struct drm_rockchip_rga_exec)
+
+#endif /* _UAPI_ROCKCHIP_DRM_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 3/4] ARM: dts: rockchip: add RGA device node for RK3288
@ 2016-03-21  9:42   ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:42 UTC (permalink / raw)
  To: David Airlie, Mark Yao, Heiko Stuebner
  Cc: Joonyoung Shim, Kumar Gala, Ian Campbell, Rob Herring,
	Pawel Moll, Russell King, devicetree, linux-kernel, dri-devel,
	linux-rockchip, linux-arm-kernel, Yakir Yang

This patch add the RGA dt config of rk3288 SoC.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
 arch/arm/boot/dts/rk3288.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 8ac49f3..af948b9 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -795,6 +795,19 @@
 		status = "okay";
 	};
 
+	rga: rga@ff920000 {
+		compatible = "rockchip,rk3288-rga";
+		reg = <0xff920000 0x180>;
+		interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "rga";
+		clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>;
+		clock-names = "aclk", "hclk", "sclk";
+
+		resets = <&cru SRST_RGA_CORE>, <&cru SRST_RGA_AXI>, <&cru SRST_RGA_AHB>;
+		reset-names = "sclk", "aclk", "hclk";
+		status = "disabled";
+	};
+
 	vopb: vop@ff930000 {
 		compatible = "rockchip,rk3288-vop";
 		reg = <0xff930000 0x19c>;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 3/4] ARM: dts: rockchip: add RGA device node for RK3288
@ 2016-03-21  9:42   ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:42 UTC (permalink / raw)
  To: David Airlie, Mark Yao, Heiko Stuebner
  Cc: Joonyoung Shim, Kumar Gala, Ian Campbell, Rob Herring,
	Pawel Moll, Russell King, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Yakir Yang

This patch add the RGA dt config of rk3288 SoC.

Signed-off-by: Yakir Yang <ykk-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
 arch/arm/boot/dts/rk3288.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 8ac49f3..af948b9 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -795,6 +795,19 @@
 		status = "okay";
 	};
 
+	rga: rga@ff920000 {
+		compatible = "rockchip,rk3288-rga";
+		reg = <0xff920000 0x180>;
+		interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "rga";
+		clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>;
+		clock-names = "aclk", "hclk", "sclk";
+
+		resets = <&cru SRST_RGA_CORE>, <&cru SRST_RGA_AXI>, <&cru SRST_RGA_AHB>;
+		reset-names = "sclk", "aclk", "hclk";
+		status = "disabled";
+	};
+
 	vopb: vop@ff930000 {
 		compatible = "rockchip,rk3288-vop";
 		reg = <0xff930000 0x19c>;
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 3/4] ARM: dts: rockchip: add RGA device node for RK3288
@ 2016-03-21  9:42   ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:42 UTC (permalink / raw)
  To: linux-arm-kernel

This patch add the RGA dt config of rk3288 SoC.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
 arch/arm/boot/dts/rk3288.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 8ac49f3..af948b9 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -795,6 +795,19 @@
 		status = "okay";
 	};
 
+	rga: rga at ff920000 {
+		compatible = "rockchip,rk3288-rga";
+		reg = <0xff920000 0x180>;
+		interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "rga";
+		clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>;
+		clock-names = "aclk", "hclk", "sclk";
+
+		resets = <&cru SRST_RGA_CORE>, <&cru SRST_RGA_AXI>, <&cru SRST_RGA_AHB>;
+		reset-names = "sclk", "aclk", "hclk";
+		status = "disabled";
+	};
+
 	vopb: vop at ff930000 {
 		compatible = "rockchip,rk3288-vop";
 		reg = <0xff930000 0x19c>;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 4/4] ARM: dst: rockchip: enable RGA support on veyron devices
  2016-03-21  9:28 ` Yakir Yang
  (?)
@ 2016-03-21  9:42   ` Yakir Yang
  -1 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:42 UTC (permalink / raw)
  To: David Airlie, Mark Yao, Heiko Stuebner
  Cc: Joonyoung Shim, Kumar Gala, Ian Campbell, Rob Herring,
	Pawel Moll, Russell King, devicetree, linux-kernel, dri-devel,
	linux-rockchip, linux-arm-kernel, Yakir Yang

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
 arch/arm/boot/dts/rk3288-veyron.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi
index 9fce91f..5eb4e97 100644
--- a/arch/arm/boot/dts/rk3288-veyron.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron.dtsi
@@ -425,6 +425,10 @@
 	dr_mode = "host";
 };
 
+&rga {
+	status = "okay";
+};
+
 &vopb {
 	status = "okay";
 };
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 4/4] ARM: dst: rockchip: enable RGA support on veyron devices
@ 2016-03-21  9:42   ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:42 UTC (permalink / raw)
  To: David Airlie, Mark Yao, Heiko Stuebner
  Cc: devicetree, Russell King, Pawel Moll, Ian Campbell, linux-kernel,
	dri-devel, linux-rockchip, Rob Herring, Kumar Gala,
	linux-arm-kernel

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
 arch/arm/boot/dts/rk3288-veyron.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi
index 9fce91f..5eb4e97 100644
--- a/arch/arm/boot/dts/rk3288-veyron.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron.dtsi
@@ -425,6 +425,10 @@
 	dr_mode = "host";
 };
 
+&rga {
+	status = "okay";
+};
+
 &vopb {
 	status = "okay";
 };
-- 
1.9.1


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 4/4] ARM: dst: rockchip: enable RGA support on veyron devices
@ 2016-03-21  9:42   ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21  9:42 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
 arch/arm/boot/dts/rk3288-veyron.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi
index 9fce91f..5eb4e97 100644
--- a/arch/arm/boot/dts/rk3288-veyron.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron.dtsi
@@ -425,6 +425,10 @@
 	dr_mode = "host";
 };
 
+&rga {
+	status = "okay";
+};
+
 &vopb {
 	status = "okay";
 };
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-21  9:28 ` Yakir Yang
  (?)
@ 2016-03-21 11:29   ` Heiko Stübner
  -1 siblings, 0 replies; 73+ messages in thread
From: Heiko Stübner @ 2016-03-21 11:29 UTC (permalink / raw)
  To: Yakir Yang
  Cc: David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala, Ian Campbell,
	Rob Herring, Pawel Moll, Russell King, devicetree, linux-kernel,
	dri-devel, linux-rockchip, linux-arm-kernel

Hi Yakir,

Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
> This patch set would add the RGA direct rendering based 2d graphics
> acceleration module.

very cool to see that.

> This patch set is based on git repository below:
> git://people.freedesktop.org/~airlied/linux drm-next
> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> 
> And the RGA driver is based on Exynos G2D driver, it only manages the
> command lists received from user, so user should make the command list
> to data and registers needed by operation to use.
> 
> I have prepared an userspace demo application for testing:
> 	https://github.com/yakir-Yang/libdrm-rockchip
> That is a rockchip libdrm library, and I have write a simple test case
> "rockchip_rga_test" that would test the below RGA features:
> - solid
> - copy
> - rotation
> - flip
> - window clip
> - dithering

Did you submit your libdrm changes as well?

Userspace-interfaces need to be stable so the other side must also get 
accepted - even before the kernel change if I remember correctly.


Heiko

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-21 11:29   ` Heiko Stübner
  0 siblings, 0 replies; 73+ messages in thread
From: Heiko Stübner @ 2016-03-21 11:29 UTC (permalink / raw)
  To: Yakir Yang
  Cc: devicetree, Russell King, Pawel Moll, Ian Campbell, linux-kernel,
	dri-devel, linux-rockchip, Rob Herring, Kumar Gala,
	linux-arm-kernel

Hi Yakir,

Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
> This patch set would add the RGA direct rendering based 2d graphics
> acceleration module.

very cool to see that.

> This patch set is based on git repository below:
> git://people.freedesktop.org/~airlied/linux drm-next
> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> 
> And the RGA driver is based on Exynos G2D driver, it only manages the
> command lists received from user, so user should make the command list
> to data and registers needed by operation to use.
> 
> I have prepared an userspace demo application for testing:
> 	https://github.com/yakir-Yang/libdrm-rockchip
> That is a rockchip libdrm library, and I have write a simple test case
> "rockchip_rga_test" that would test the below RGA features:
> - solid
> - copy
> - rotation
> - flip
> - window clip
> - dithering

Did you submit your libdrm changes as well?

Userspace-interfaces need to be stable so the other side must also get 
accepted - even before the kernel change if I remember correctly.


Heiko
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-21 11:29   ` Heiko Stübner
  0 siblings, 0 replies; 73+ messages in thread
From: Heiko Stübner @ 2016-03-21 11:29 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Yakir,

Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
> This patch set would add the RGA direct rendering based 2d graphics
> acceleration module.

very cool to see that.

> This patch set is based on git repository below:
> git://people.freedesktop.org/~airlied/linux drm-next
> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> 
> And the RGA driver is based on Exynos G2D driver, it only manages the
> command lists received from user, so user should make the command list
> to data and registers needed by operation to use.
> 
> I have prepared an userspace demo application for testing:
> 	https://github.com/yakir-Yang/libdrm-rockchip
> That is a rockchip libdrm library, and I have write a simple test case
> "rockchip_rga_test" that would test the below RGA features:
> - solid
> - copy
> - rotation
> - flip
> - window clip
> - dithering

Did you submit your libdrm changes as well?

Userspace-interfaces need to be stable so the other side must also get 
accepted - even before the kernel change if I remember correctly.


Heiko

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-21 11:29   ` Heiko Stübner
  (?)
@ 2016-03-21 12:17     ` Yakir Yang
  -1 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21 12:17 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala, Ian Campbell,
	Rob Herring, Pawel Moll, Russell King, devicetree, linux-kernel,
	dri-devel, linux-rockchip, linux-arm-kernel

Hi Heiko,

On 03/21/2016 07:29 PM, Heiko Stübner wrote:
> Hi Yakir,
>
> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>> This patch set would add the RGA direct rendering based 2d graphics
>> acceleration module.
> very cool to see that.
;)
>> This patch set is based on git repository below:
>> git://people.freedesktop.org/~airlied/linux drm-next
>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>
>> And the RGA driver is based on Exynos G2D driver, it only manages the
>> command lists received from user, so user should make the command list
>> to data and registers needed by operation to use.
>>
>> I have prepared an userspace demo application for testing:
>> 	https://github.com/yakir-Yang/libdrm-rockchip
>> That is a rockchip libdrm library, and I have write a simple test case
>> "rockchip_rga_test" that would test the below RGA features:
>> - solid
>> - copy
>> - rotation
>> - flip
>> - window clip
>> - dithering
> Did you submit your libdrm changes as well?
>
> Userspace-interfaces need to be stable so the other side must also get
> accepted - even before the kernel change if I remember correctly.

Got it, and I just saw exynos_fimg2d already landed at mainline libdrm. 
But I don't find the way to submit patches to libdrm, would you like 
share some helps here ;)

- Yakir

>
> Heiko
>
>
>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-21 12:17     ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21 12:17 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala, Ian Campbell,
	Rob Herring, Pawel Moll, Russell King,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Heiko,

On 03/21/2016 07:29 PM, Heiko Stübner wrote:
> Hi Yakir,
>
> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>> This patch set would add the RGA direct rendering based 2d graphics
>> acceleration module.
> very cool to see that.
;)
>> This patch set is based on git repository below:
>> git://people.freedesktop.org/~airlied/linux drm-next
>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>
>> And the RGA driver is based on Exynos G2D driver, it only manages the
>> command lists received from user, so user should make the command list
>> to data and registers needed by operation to use.
>>
>> I have prepared an userspace demo application for testing:
>> 	https://github.com/yakir-Yang/libdrm-rockchip
>> That is a rockchip libdrm library, and I have write a simple test case
>> "rockchip_rga_test" that would test the below RGA features:
>> - solid
>> - copy
>> - rotation
>> - flip
>> - window clip
>> - dithering
> Did you submit your libdrm changes as well?
>
> Userspace-interfaces need to be stable so the other side must also get
> accepted - even before the kernel change if I remember correctly.

Got it, and I just saw exynos_fimg2d already landed at mainline libdrm. 
But I don't find the way to submit patches to libdrm, would you like 
share some helps here ;)

- Yakir

>
> Heiko
>
>
>


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-21 12:17     ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-21 12:17 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Heiko,

On 03/21/2016 07:29 PM, Heiko St?bner wrote:
> Hi Yakir,
>
> Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
>> This patch set would add the RGA direct rendering based 2d graphics
>> acceleration module.
> very cool to see that.
;)
>> This patch set is based on git repository below:
>> git://people.freedesktop.org/~airlied/linux drm-next
>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>
>> And the RGA driver is based on Exynos G2D driver, it only manages the
>> command lists received from user, so user should make the command list
>> to data and registers needed by operation to use.
>>
>> I have prepared an userspace demo application for testing:
>> 	https://github.com/yakir-Yang/libdrm-rockchip
>> That is a rockchip libdrm library, and I have write a simple test case
>> "rockchip_rga_test" that would test the below RGA features:
>> - solid
>> - copy
>> - rotation
>> - flip
>> - window clip
>> - dithering
> Did you submit your libdrm changes as well?
>
> Userspace-interfaces need to be stable so the other side must also get
> accepted - even before the kernel change if I remember correctly.

Got it, and I just saw exynos_fimg2d already landed at mainline libdrm. 
But I don't find the way to submit patches to libdrm, would you like 
share some helps here ;)

- Yakir

>
> Heiko
>
>
>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-21 12:17     ` Yakir Yang
  (?)
@ 2016-03-22  0:42       ` Heiko Stuebner
  -1 siblings, 0 replies; 73+ messages in thread
From: Heiko Stuebner @ 2016-03-22  0:42 UTC (permalink / raw)
  To: Yakir Yang
  Cc: David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala, Ian Campbell,
	Rob Herring, Pawel Moll, Russell King, devicetree, linux-kernel,
	dri-devel, linux-rockchip, linux-arm-kernel, Emil Velikov

Hi Yakir,

Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
> > Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
> >> This patch set would add the RGA direct rendering based 2d graphics
> >> acceleration module.
> > 
> > very cool to see that.
> 
> ;)
> 
> >> This patch set is based on git repository below:
> >> git://people.freedesktop.org/~airlied/linux drm-next
> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> >> 
> >> And the RGA driver is based on Exynos G2D driver, it only manages the
> >> command lists received from user, so user should make the command list
> >> to data and registers needed by operation to use.
> >> 
> >> I have prepared an userspace demo application for testing:
> >> 	https://github.com/yakir-Yang/libdrm-rockchip
> >> 
> >> That is a rockchip libdrm library, and I have write a simple test case
> >> "rockchip_rga_test" that would test the below RGA features:
> >> - solid
> >> - copy
> >> - rotation
> >> - flip
> >> - window clip
> >> - dithering
> > 
> > Did you submit your libdrm changes as well?
> > 
> > Userspace-interfaces need to be stable so the other side must also get
> > accepted - even before the kernel change if I remember correctly.
> 
> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
> But I don't find the way to submit patches to libdrm, would you like
> share some helps here ;)

Looking at the libdrm sources on cgit.freedesktop.org, I did not find any 
specific manual on submitting patches.

But looking at the dri-list archive, dri-devel@lists.freedesktop.org is the 
right list and looking at the libdrm history it looks like Emil Velikov 
<emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
And as a 3rd recipient, please also include the linux-rockchip list.

@Emil, please shout if I read that wrong :-)


Hope that helps
Heiko

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-22  0:42       ` Heiko Stuebner
  0 siblings, 0 replies; 73+ messages in thread
From: Heiko Stuebner @ 2016-03-22  0:42 UTC (permalink / raw)
  To: Yakir Yang
  Cc: devicetree, Russell King, Pawel Moll, Ian Campbell, Emil Velikov,
	linux-kernel, dri-devel, linux-rockchip, Rob Herring, Kumar Gala,
	linux-arm-kernel

Hi Yakir,

Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
> > Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
> >> This patch set would add the RGA direct rendering based 2d graphics
> >> acceleration module.
> > 
> > very cool to see that.
> 
> ;)
> 
> >> This patch set is based on git repository below:
> >> git://people.freedesktop.org/~airlied/linux drm-next
> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> >> 
> >> And the RGA driver is based on Exynos G2D driver, it only manages the
> >> command lists received from user, so user should make the command list
> >> to data and registers needed by operation to use.
> >> 
> >> I have prepared an userspace demo application for testing:
> >> 	https://github.com/yakir-Yang/libdrm-rockchip
> >> 
> >> That is a rockchip libdrm library, and I have write a simple test case
> >> "rockchip_rga_test" that would test the below RGA features:
> >> - solid
> >> - copy
> >> - rotation
> >> - flip
> >> - window clip
> >> - dithering
> > 
> > Did you submit your libdrm changes as well?
> > 
> > Userspace-interfaces need to be stable so the other side must also get
> > accepted - even before the kernel change if I remember correctly.
> 
> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
> But I don't find the way to submit patches to libdrm, would you like
> share some helps here ;)

Looking at the libdrm sources on cgit.freedesktop.org, I did not find any 
specific manual on submitting patches.

But looking at the dri-list archive, dri-devel@lists.freedesktop.org is the 
right list and looking at the libdrm history it looks like Emil Velikov 
<emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
And as a 3rd recipient, please also include the linux-rockchip list.

@Emil, please shout if I read that wrong :-)


Hope that helps
Heiko
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-22  0:42       ` Heiko Stuebner
  0 siblings, 0 replies; 73+ messages in thread
From: Heiko Stuebner @ 2016-03-22  0:42 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Yakir,

Am Montag, 21. M?rz 2016, 20:17:46 schrieb Yakir Yang:
> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
> > Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
> >> This patch set would add the RGA direct rendering based 2d graphics
> >> acceleration module.
> > 
> > very cool to see that.
> 
> ;)
> 
> >> This patch set is based on git repository below:
> >> git://people.freedesktop.org/~airlied/linux drm-next
> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> >> 
> >> And the RGA driver is based on Exynos G2D driver, it only manages the
> >> command lists received from user, so user should make the command list
> >> to data and registers needed by operation to use.
> >> 
> >> I have prepared an userspace demo application for testing:
> >> 	https://github.com/yakir-Yang/libdrm-rockchip
> >> 
> >> That is a rockchip libdrm library, and I have write a simple test case
> >> "rockchip_rga_test" that would test the below RGA features:
> >> - solid
> >> - copy
> >> - rotation
> >> - flip
> >> - window clip
> >> - dithering
> > 
> > Did you submit your libdrm changes as well?
> > 
> > Userspace-interfaces need to be stable so the other side must also get
> > accepted - even before the kernel change if I remember correctly.
> 
> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
> But I don't find the way to submit patches to libdrm, would you like
> share some helps here ;)

Looking at the libdrm sources on cgit.freedesktop.org, I did not find any 
specific manual on submitting patches.

But looking at the dri-list archive, dri-devel at lists.freedesktop.org is the 
right list and looking at the libdrm history it looks like Emil Velikov 
<emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
And as a 3rd recipient, please also include the linux-rockchip list.

@Emil, please shout if I read that wrong :-)


Hope that helps
Heiko

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-22  0:42       ` Heiko Stuebner
  (?)
@ 2016-03-22  2:14         ` Yakir Yang
  -1 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-22  2:14 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala, Ian Campbell,
	Rob Herring, Pawel Moll, Russell King, devicetree, linux-kernel,
	dri-devel, linux-rockchip, linux-arm-kernel, Emil Velikov

Hi Heiko,

On 03/22/2016 08:42 AM, Heiko Stuebner wrote:
> Hi Yakir,
>
> Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>>> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>> acceleration module.
>>> very cool to see that.
>> ;)
>>
>>>> This patch set is based on git repository below:
>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>
>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>> command lists received from user, so user should make the command list
>>>> to data and registers needed by operation to use.
>>>>
>>>> I have prepared an userspace demo application for testing:
>>>> 	https://github.com/yakir-Yang/libdrm-rockchip
>>>>
>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>> "rockchip_rga_test" that would test the below RGA features:
>>>> - solid
>>>> - copy
>>>> - rotation
>>>> - flip
>>>> - window clip
>>>> - dithering
>>> Did you submit your libdrm changes as well?
>>>
>>> Userspace-interfaces need to be stable so the other side must also get
>>> accepted - even before the kernel change if I remember correctly.
>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>> But I don't find the way to submit patches to libdrm, would you like
>> share some helps here ;)
> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
> specific manual on submitting patches.
>
> But looking at the dri-list archive, dri-devel@lists.freedesktop.org is the
> right list and looking at the libdrm history it looks like Emil Velikov
> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
> And as a 3rd recipient, please also include the linux-rockchip list.
Great, thanks, I would improve my libdrm changes, and submit them soon :)

- Yakir
> @Emil, please shout if I read that wrong :-)
>
>
> Hope that helps
> Heiko
>
>
>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-22  2:14         ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-22  2:14 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala, Ian Campbell,
	Rob Herring, Pawel Moll, Russell King,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Emil Velikov

Hi Heiko,

On 03/22/2016 08:42 AM, Heiko Stuebner wrote:
> Hi Yakir,
>
> Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>>> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>> acceleration module.
>>> very cool to see that.
>> ;)
>>
>>>> This patch set is based on git repository below:
>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>
>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>> command lists received from user, so user should make the command list
>>>> to data and registers needed by operation to use.
>>>>
>>>> I have prepared an userspace demo application for testing:
>>>> 	https://github.com/yakir-Yang/libdrm-rockchip
>>>>
>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>> "rockchip_rga_test" that would test the below RGA features:
>>>> - solid
>>>> - copy
>>>> - rotation
>>>> - flip
>>>> - window clip
>>>> - dithering
>>> Did you submit your libdrm changes as well?
>>>
>>> Userspace-interfaces need to be stable so the other side must also get
>>> accepted - even before the kernel change if I remember correctly.
>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>> But I don't find the way to submit patches to libdrm, would you like
>> share some helps here ;)
> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
> specific manual on submitting patches.
>
> But looking at the dri-list archive, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org is the
> right list and looking at the libdrm history it looks like Emil Velikov
> <emil.l.velikov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> seems to be doing maintenance-stuff in libdrm.
> And as a 3rd recipient, please also include the linux-rockchip list.
Great, thanks, I would improve my libdrm changes, and submit them soon :)

- Yakir
> @Emil, please shout if I read that wrong :-)
>
>
> Hope that helps
> Heiko
>
>
>


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-22  2:14         ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-22  2:14 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Heiko,

On 03/22/2016 08:42 AM, Heiko Stuebner wrote:
> Hi Yakir,
>
> Am Montag, 21. M?rz 2016, 20:17:46 schrieb Yakir Yang:
>> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
>>> Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>> acceleration module.
>>> very cool to see that.
>> ;)
>>
>>>> This patch set is based on git repository below:
>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>
>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>> command lists received from user, so user should make the command list
>>>> to data and registers needed by operation to use.
>>>>
>>>> I have prepared an userspace demo application for testing:
>>>> 	https://github.com/yakir-Yang/libdrm-rockchip
>>>>
>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>> "rockchip_rga_test" that would test the below RGA features:
>>>> - solid
>>>> - copy
>>>> - rotation
>>>> - flip
>>>> - window clip
>>>> - dithering
>>> Did you submit your libdrm changes as well?
>>>
>>> Userspace-interfaces need to be stable so the other side must also get
>>> accepted - even before the kernel change if I remember correctly.
>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>> But I don't find the way to submit patches to libdrm, would you like
>> share some helps here ;)
> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
> specific manual on submitting patches.
>
> But looking at the dri-list archive, dri-devel at lists.freedesktop.org is the
> right list and looking at the libdrm history it looks like Emil Velikov
> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
> And as a 3rd recipient, please also include the linux-rockchip list.
Great, thanks, I would improve my libdrm changes, and submit them soon :)

- Yakir
> @Emil, please shout if I read that wrong :-)
>
>
> Hope that helps
> Heiko
>
>
>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-21 12:17     ` Yakir Yang
@ 2016-03-22 10:24       ` Andreas Färber
  -1 siblings, 0 replies; 73+ messages in thread
From: Andreas Färber @ 2016-03-22 10:24 UTC (permalink / raw)
  To: Yakir Yang
  Cc: Heiko Stübner, devicetree, Russell King, Joonyoung Shim,
	Pawel Moll, Ian Campbell, David Airlie, linux-kernel, dri-devel,
	linux-rockchip, Rob Herring, Kumar Gala, linux-arm-kernel,
	Mark Yao

Hi Yakir,

Am 21.03.2016 um 13:17 schrieb Yakir Yang:
> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>>> This patch set would add the RGA direct rendering based 2d graphics
>>> acceleration module.
>> very cool to see that.
> ;)
>>> This patch set is based on git repository below:
>>> git://people.freedesktop.org/~airlied/linux drm-next
>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>
>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>> command lists received from user, so user should make the command list
>>> to data and registers needed by operation to use.
>>>
>>> I have prepared an userspace demo application for testing:
>>>     https://github.com/yakir-Yang/libdrm-rockchip
>>> That is a rockchip libdrm library, and I have write a simple test case
>>> "rockchip_rga_test" that would test the below RGA features:
>>> - solid
>>> - copy
>>> - rotation
>>> - flip
>>> - window clip
>>> - dithering
>> Did you submit your libdrm changes as well?
>>
>> Userspace-interfaces need to be stable so the other side must also get
>> accepted - even before the kernel change if I remember correctly.
> 
> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
> But I don't find the way to submit patches to libdrm, would you like
> share some helps here ;)

If you're using Exynos as an example, please keep in mind that the
libdrm license is MIT/X11, not GPL as the kernel. For our Linux distro
we had to disable some Exynos parts because they snuck some GPL code in
there and redistributing libdrm under GPL would cause a big headache
(review of all packages directly or indirectly linking against it).

Thanks,
Andreas

-- 
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton; HRB 21284 (AG Nürnberg)

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-22 10:24       ` Andreas Färber
  0 siblings, 0 replies; 73+ messages in thread
From: Andreas Färber @ 2016-03-22 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Yakir,

Am 21.03.2016 um 13:17 schrieb Yakir Yang:
> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
>> Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
>>> This patch set would add the RGA direct rendering based 2d graphics
>>> acceleration module.
>> very cool to see that.
> ;)
>>> This patch set is based on git repository below:
>>> git://people.freedesktop.org/~airlied/linux drm-next
>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>
>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>> command lists received from user, so user should make the command list
>>> to data and registers needed by operation to use.
>>>
>>> I have prepared an userspace demo application for testing:
>>>     https://github.com/yakir-Yang/libdrm-rockchip
>>> That is a rockchip libdrm library, and I have write a simple test case
>>> "rockchip_rga_test" that would test the below RGA features:
>>> - solid
>>> - copy
>>> - rotation
>>> - flip
>>> - window clip
>>> - dithering
>> Did you submit your libdrm changes as well?
>>
>> Userspace-interfaces need to be stable so the other side must also get
>> accepted - even before the kernel change if I remember correctly.
> 
> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
> But I don't find the way to submit patches to libdrm, would you like
> share some helps here ;)

If you're using Exynos as an example, please keep in mind that the
libdrm license is MIT/X11, not GPL as the kernel. For our Linux distro
we had to disable some Exynos parts because they snuck some GPL code in
there and redistributing libdrm under GPL would cause a big headache
(review of all packages directly or indirectly linking against it).

Thanks,
Andreas

-- 
SUSE Linux GmbH, Maxfeldstr. 5, 90409 N?rnberg, Germany
GF: Felix Imend?rffer, Jane Smithard, Graham Norton; HRB 21284 (AG N?rnberg)

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-22  0:42       ` Heiko Stuebner
  (?)
@ 2016-03-28 12:21         ` Emil Velikov
  -1 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-28 12:21 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: Yakir Yang, David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	LAKML

On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
> Hi Yakir,
>
> Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>> > Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>> >> This patch set would add the RGA direct rendering based 2d graphics
>> >> acceleration module.
>> >
>> > very cool to see that.
>>
>> ;)
>>
>> >> This patch set is based on git repository below:
>> >> git://people.freedesktop.org/~airlied/linux drm-next
>> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>> >>
>> >> And the RGA driver is based on Exynos G2D driver, it only manages the
>> >> command lists received from user, so user should make the command list
>> >> to data and registers needed by operation to use.
>> >>
>> >> I have prepared an userspace demo application for testing:
>> >>    https://github.com/yakir-Yang/libdrm-rockchip
>> >>
>> >> That is a rockchip libdrm library, and I have write a simple test case
>> >> "rockchip_rga_test" that would test the below RGA features:
>> >> - solid
>> >> - copy
>> >> - rotation
>> >> - flip
>> >> - window clip
>> >> - dithering
>> >
>> > Did you submit your libdrm changes as well?
>> >
>> > Userspace-interfaces need to be stable so the other side must also get
>> > accepted - even before the kernel change if I remember correctly.
>>
>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>> But I don't find the way to submit patches to libdrm, would you like
>> share some helps here ;)
>
> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
> specific manual on submitting patches.
>
> But looking at the dri-list archive, dri-devel@lists.freedesktop.org is the
> right list and looking at the libdrm history it looks like Emil Velikov
> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
> And as a 3rd recipient, please also include the linux-rockchip list.
>
> @Emil, please shout if I read that wrong :-)
>
You got it spot on Heiko. There are a few notes though...

As one reuses the existing hardware/IP block, it would be better to
avoid copy/pasting code around.
Namely:
 - (if possible) factor out the exynos g2d kernel functionality to a
separate kernel module and wire up the rockhip (via dt ?) to use it
 - factor out the g2d specifics out of exynos_drm.h (into
exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
new header
 - if neither of these are possible, then please ensure that the new
header uses correct types (see the docs [1]), use MIT/X11 license (if
possible) and link where upstream userspace is happy with the
interface (ideally more than a simple test app like libdrm)

These might sound like an overkill, although getting UAPI right and
maintaining it forever forces us to do so.

Regards,
Emil

[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/ioctl/botching-up-ioctls.txt

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-28 12:21         ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-28 12:21 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: devicetree, Russell King, Pawel Moll, Ian Campbell,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	Rob Herring, Kumar Gala, LAKML

On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
> Hi Yakir,
>
> Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>> > Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>> >> This patch set would add the RGA direct rendering based 2d graphics
>> >> acceleration module.
>> >
>> > very cool to see that.
>>
>> ;)
>>
>> >> This patch set is based on git repository below:
>> >> git://people.freedesktop.org/~airlied/linux drm-next
>> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>> >>
>> >> And the RGA driver is based on Exynos G2D driver, it only manages the
>> >> command lists received from user, so user should make the command list
>> >> to data and registers needed by operation to use.
>> >>
>> >> I have prepared an userspace demo application for testing:
>> >>    https://github.com/yakir-Yang/libdrm-rockchip
>> >>
>> >> That is a rockchip libdrm library, and I have write a simple test case
>> >> "rockchip_rga_test" that would test the below RGA features:
>> >> - solid
>> >> - copy
>> >> - rotation
>> >> - flip
>> >> - window clip
>> >> - dithering
>> >
>> > Did you submit your libdrm changes as well?
>> >
>> > Userspace-interfaces need to be stable so the other side must also get
>> > accepted - even before the kernel change if I remember correctly.
>>
>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>> But I don't find the way to submit patches to libdrm, would you like
>> share some helps here ;)
>
> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
> specific manual on submitting patches.
>
> But looking at the dri-list archive, dri-devel@lists.freedesktop.org is the
> right list and looking at the libdrm history it looks like Emil Velikov
> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
> And as a 3rd recipient, please also include the linux-rockchip list.
>
> @Emil, please shout if I read that wrong :-)
>
You got it spot on Heiko. There are a few notes though...

As one reuses the existing hardware/IP block, it would be better to
avoid copy/pasting code around.
Namely:
 - (if possible) factor out the exynos g2d kernel functionality to a
separate kernel module and wire up the rockhip (via dt ?) to use it
 - factor out the g2d specifics out of exynos_drm.h (into
exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
new header
 - if neither of these are possible, then please ensure that the new
header uses correct types (see the docs [1]), use MIT/X11 license (if
possible) and link where upstream userspace is happy with the
interface (ideally more than a simple test app like libdrm)

These might sound like an overkill, although getting UAPI right and
maintaining it forever forces us to do so.

Regards,
Emil

[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/ioctl/botching-up-ioctls.txt
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-28 12:21         ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-28 12:21 UTC (permalink / raw)
  To: linux-arm-kernel

On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
> Hi Yakir,
>
> Am Montag, 21. M?rz 2016, 20:17:46 schrieb Yakir Yang:
>> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
>> > Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
>> >> This patch set would add the RGA direct rendering based 2d graphics
>> >> acceleration module.
>> >
>> > very cool to see that.
>>
>> ;)
>>
>> >> This patch set is based on git repository below:
>> >> git://people.freedesktop.org/~airlied/linux drm-next
>> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>> >>
>> >> And the RGA driver is based on Exynos G2D driver, it only manages the
>> >> command lists received from user, so user should make the command list
>> >> to data and registers needed by operation to use.
>> >>
>> >> I have prepared an userspace demo application for testing:
>> >>    https://github.com/yakir-Yang/libdrm-rockchip
>> >>
>> >> That is a rockchip libdrm library, and I have write a simple test case
>> >> "rockchip_rga_test" that would test the below RGA features:
>> >> - solid
>> >> - copy
>> >> - rotation
>> >> - flip
>> >> - window clip
>> >> - dithering
>> >
>> > Did you submit your libdrm changes as well?
>> >
>> > Userspace-interfaces need to be stable so the other side must also get
>> > accepted - even before the kernel change if I remember correctly.
>>
>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>> But I don't find the way to submit patches to libdrm, would you like
>> share some helps here ;)
>
> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
> specific manual on submitting patches.
>
> But looking at the dri-list archive, dri-devel at lists.freedesktop.org is the
> right list and looking at the libdrm history it looks like Emil Velikov
> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
> And as a 3rd recipient, please also include the linux-rockchip list.
>
> @Emil, please shout if I read that wrong :-)
>
You got it spot on Heiko. There are a few notes though...

As one reuses the existing hardware/IP block, it would be better to
avoid copy/pasting code around.
Namely:
 - (if possible) factor out the exynos g2d kernel functionality to a
separate kernel module and wire up the rockhip (via dt ?) to use it
 - factor out the g2d specifics out of exynos_drm.h (into
exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
new header
 - if neither of these are possible, then please ensure that the new
header uses correct types (see the docs [1]), use MIT/X11 license (if
possible) and link where upstream userspace is happy with the
interface (ideally more than a simple test app like libdrm)

These might sound like an overkill, although getting UAPI right and
maintaining it forever forces us to do so.

Regards,
Emil

[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/ioctl/botching-up-ioctls.txt

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-28 12:21         ` Emil Velikov
  (?)
@ 2016-03-28 18:44           ` Heiko Stübner
  -1 siblings, 0 replies; 73+ messages in thread
From: Heiko Stübner @ 2016-03-28 18:44 UTC (permalink / raw)
  To: Emil Velikov
  Cc: Yakir Yang, David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	linux-kernel, ML dri-devel, linux-rockchip, LAKML

Am Montag, 28. März 2016, 13:21:02 schrieb Emil Velikov:
> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
> > Hi Yakir,
> > 
> > Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
> >> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
> >> > Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
> >> >> This patch set would add the RGA direct rendering based 2d graphics
> >> >> acceleration module.
> >> > 
> >> > very cool to see that.
> >> 
> >> ;)
> >> 
> >> >> This patch set is based on git repository below:
> >> >> git://people.freedesktop.org/~airlied/linux drm-next
> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> >> >> 
> >> >> And the RGA driver is based on Exynos G2D driver, it only manages the
> >> >> command lists received from user, so user should make the command list
> >> >> to data and registers needed by operation to use.
> >> >> 
> >> >> I have prepared an userspace demo application for testing:
> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
> >> >> 
> >> >> That is a rockchip libdrm library, and I have write a simple test case
> >> >> "rockchip_rga_test" that would test the below RGA features:
> >> >> - solid
> >> >> - copy
> >> >> - rotation
> >> >> - flip
> >> >> - window clip
> >> >> - dithering
> >> > 
> >> > Did you submit your libdrm changes as well?
> >> > 
> >> > Userspace-interfaces need to be stable so the other side must also get
> >> > accepted - even before the kernel change if I remember correctly.
> >> 
> >> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
> >> But I don't find the way to submit patches to libdrm, would you like
> >> share some helps here ;)
> > 
> > Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
> > specific manual on submitting patches.
> > 
> > But looking at the dri-list archive, dri-devel@lists.freedesktop.org is
> > the
> > right list and looking at the libdrm history it looks like Emil Velikov
> > <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
> > And as a 3rd recipient, please also include the linux-rockchip list.
> > 
> > @Emil, please shout if I read that wrong :-)
> 
> You got it spot on Heiko. There are a few notes though...
> 
> As one reuses the existing hardware/IP block, it would be better to
> avoid copy/pasting code around.
> Namely:
>  - (if possible) factor out the exynos g2d kernel functionality to a
> separate kernel module and wire up the rockhip (via dt ?) to use it
>  - factor out the g2d specifics out of exynos_drm.h (into
> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
> new header

I think the IP blocks themself are quite different between Rockchip's RGA and 
Samsung's g2d and I guess the similarities are more along the lines on how 
that gets integrated into the respective drm driver and userspace.


>  - if neither of these are possible, then please ensure that the new
> header uses correct types (see the docs [1]), use MIT/X11 license (if
> possible) and link where upstream userspace is happy with the
> interface (ideally more than a simple test app like libdrm)
> These might sound like an overkill, although getting UAPI right and
> maintaining it forever forces us to do so.

As for a real-world usecase, maybe the armsoc xserver might be somewhat easy 
to use. While the core changes I did are in the core project already, I'm 
still keeping the actual Rockchip support separate [0] due to the not-yet-
resolved create_gem ioctl.

Anyway, the armsoc xserver has some exa implementation hooks were I guess it 
might be relatively easy to hook up soc-specific things.

[0] https://github.com/mmind/xf86-video-armsoc/tree/devel/rockchip

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-28 18:44           ` Heiko Stübner
  0 siblings, 0 replies; 73+ messages in thread
From: Heiko Stübner @ 2016-03-28 18:44 UTC (permalink / raw)
  To: Emil Velikov
  Cc: devicetree, Russell King, Pawel Moll, Ian Campbell, linux-kernel,
	ML dri-devel, linux-rockchip, Rob Herring, Kumar Gala, LAKML

Am Montag, 28. März 2016, 13:21:02 schrieb Emil Velikov:
> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
> > Hi Yakir,
> > 
> > Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
> >> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
> >> > Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
> >> >> This patch set would add the RGA direct rendering based 2d graphics
> >> >> acceleration module.
> >> > 
> >> > very cool to see that.
> >> 
> >> ;)
> >> 
> >> >> This patch set is based on git repository below:
> >> >> git://people.freedesktop.org/~airlied/linux drm-next
> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> >> >> 
> >> >> And the RGA driver is based on Exynos G2D driver, it only manages the
> >> >> command lists received from user, so user should make the command list
> >> >> to data and registers needed by operation to use.
> >> >> 
> >> >> I have prepared an userspace demo application for testing:
> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
> >> >> 
> >> >> That is a rockchip libdrm library, and I have write a simple test case
> >> >> "rockchip_rga_test" that would test the below RGA features:
> >> >> - solid
> >> >> - copy
> >> >> - rotation
> >> >> - flip
> >> >> - window clip
> >> >> - dithering
> >> > 
> >> > Did you submit your libdrm changes as well?
> >> > 
> >> > Userspace-interfaces need to be stable so the other side must also get
> >> > accepted - even before the kernel change if I remember correctly.
> >> 
> >> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
> >> But I don't find the way to submit patches to libdrm, would you like
> >> share some helps here ;)
> > 
> > Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
> > specific manual on submitting patches.
> > 
> > But looking at the dri-list archive, dri-devel@lists.freedesktop.org is
> > the
> > right list and looking at the libdrm history it looks like Emil Velikov
> > <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
> > And as a 3rd recipient, please also include the linux-rockchip list.
> > 
> > @Emil, please shout if I read that wrong :-)
> 
> You got it spot on Heiko. There are a few notes though...
> 
> As one reuses the existing hardware/IP block, it would be better to
> avoid copy/pasting code around.
> Namely:
>  - (if possible) factor out the exynos g2d kernel functionality to a
> separate kernel module and wire up the rockhip (via dt ?) to use it
>  - factor out the g2d specifics out of exynos_drm.h (into
> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
> new header

I think the IP blocks themself are quite different between Rockchip's RGA and 
Samsung's g2d and I guess the similarities are more along the lines on how 
that gets integrated into the respective drm driver and userspace.


>  - if neither of these are possible, then please ensure that the new
> header uses correct types (see the docs [1]), use MIT/X11 license (if
> possible) and link where upstream userspace is happy with the
> interface (ideally more than a simple test app like libdrm)
> These might sound like an overkill, although getting UAPI right and
> maintaining it forever forces us to do so.

As for a real-world usecase, maybe the armsoc xserver might be somewhat easy 
to use. While the core changes I did are in the core project already, I'm 
still keeping the actual Rockchip support separate [0] due to the not-yet-
resolved create_gem ioctl.

Anyway, the armsoc xserver has some exa implementation hooks were I guess it 
might be relatively easy to hook up soc-specific things.

[0] https://github.com/mmind/xf86-video-armsoc/tree/devel/rockchip

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-28 18:44           ` Heiko Stübner
  0 siblings, 0 replies; 73+ messages in thread
From: Heiko Stübner @ 2016-03-28 18:44 UTC (permalink / raw)
  To: linux-arm-kernel

Am Montag, 28. M?rz 2016, 13:21:02 schrieb Emil Velikov:
> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
> > Hi Yakir,
> > 
> > Am Montag, 21. M?rz 2016, 20:17:46 schrieb Yakir Yang:
> >> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
> >> > Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
> >> >> This patch set would add the RGA direct rendering based 2d graphics
> >> >> acceleration module.
> >> > 
> >> > very cool to see that.
> >> 
> >> ;)
> >> 
> >> >> This patch set is based on git repository below:
> >> >> git://people.freedesktop.org/~airlied/linux drm-next
> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> >> >> 
> >> >> And the RGA driver is based on Exynos G2D driver, it only manages the
> >> >> command lists received from user, so user should make the command list
> >> >> to data and registers needed by operation to use.
> >> >> 
> >> >> I have prepared an userspace demo application for testing:
> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
> >> >> 
> >> >> That is a rockchip libdrm library, and I have write a simple test case
> >> >> "rockchip_rga_test" that would test the below RGA features:
> >> >> - solid
> >> >> - copy
> >> >> - rotation
> >> >> - flip
> >> >> - window clip
> >> >> - dithering
> >> > 
> >> > Did you submit your libdrm changes as well?
> >> > 
> >> > Userspace-interfaces need to be stable so the other side must also get
> >> > accepted - even before the kernel change if I remember correctly.
> >> 
> >> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
> >> But I don't find the way to submit patches to libdrm, would you like
> >> share some helps here ;)
> > 
> > Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
> > specific manual on submitting patches.
> > 
> > But looking at the dri-list archive, dri-devel at lists.freedesktop.org is
> > the
> > right list and looking at the libdrm history it looks like Emil Velikov
> > <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
> > And as a 3rd recipient, please also include the linux-rockchip list.
> > 
> > @Emil, please shout if I read that wrong :-)
> 
> You got it spot on Heiko. There are a few notes though...
> 
> As one reuses the existing hardware/IP block, it would be better to
> avoid copy/pasting code around.
> Namely:
>  - (if possible) factor out the exynos g2d kernel functionality to a
> separate kernel module and wire up the rockhip (via dt ?) to use it
>  - factor out the g2d specifics out of exynos_drm.h (into
> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
> new header

I think the IP blocks themself are quite different between Rockchip's RGA and 
Samsung's g2d and I guess the similarities are more along the lines on how 
that gets integrated into the respective drm driver and userspace.


>  - if neither of these are possible, then please ensure that the new
> header uses correct types (see the docs [1]), use MIT/X11 license (if
> possible) and link where upstream userspace is happy with the
> interface (ideally more than a simple test app like libdrm)
> These might sound like an overkill, although getting UAPI right and
> maintaining it forever forces us to do so.

As for a real-world usecase, maybe the armsoc xserver might be somewhat easy 
to use. While the core changes I did are in the core project already, I'm 
still keeping the actual Rockchip support separate [0] due to the not-yet-
resolved create_gem ioctl.

Anyway, the armsoc xserver has some exa implementation hooks were I guess it 
might be relatively easy to hook up soc-specific things.

[0] https://github.com/mmind/xf86-video-armsoc/tree/devel/rockchip

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-28 18:44           ` Heiko Stübner
  (?)
@ 2016-03-28 21:35             ` Emil Velikov
  -1 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-28 21:35 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Yakir Yang, David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	LAKML

On 28 March 2016 at 19:44, Heiko Stübner <heiko@sntech.de> wrote:
> Am Montag, 28. März 2016, 13:21:02 schrieb Emil Velikov:
>> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
>> > Hi Yakir,
>> >
>> > Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>> >> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>> >> > Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>> >> >> This patch set would add the RGA direct rendering based 2d graphics
>> >> >> acceleration module.
>> >> >
>> >> > very cool to see that.
>> >>
>> >> ;)
>> >>
>> >> >> This patch set is based on git repository below:
>> >> >> git://people.freedesktop.org/~airlied/linux drm-next
>> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>> >> >>
>> >> >> And the RGA driver is based on Exynos G2D driver, it only manages the
>> >> >> command lists received from user, so user should make the command list
>> >> >> to data and registers needed by operation to use.
>> >> >>
>> >> >> I have prepared an userspace demo application for testing:
>> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
>> >> >>
>> >> >> That is a rockchip libdrm library, and I have write a simple test case
>> >> >> "rockchip_rga_test" that would test the below RGA features:
>> >> >> - solid
>> >> >> - copy
>> >> >> - rotation
>> >> >> - flip
>> >> >> - window clip
>> >> >> - dithering
>> >> >
>> >> > Did you submit your libdrm changes as well?
>> >> >
>> >> > Userspace-interfaces need to be stable so the other side must also get
>> >> > accepted - even before the kernel change if I remember correctly.
>> >>
>> >> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>> >> But I don't find the way to submit patches to libdrm, would you like
>> >> share some helps here ;)
>> >
>> > Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
>> > specific manual on submitting patches.
>> >
>> > But looking at the dri-list archive, dri-devel@lists.freedesktop.org is
>> > the
>> > right list and looking at the libdrm history it looks like Emil Velikov
>> > <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
>> > And as a 3rd recipient, please also include the linux-rockchip list.
>> >
>> > @Emil, please shout if I read that wrong :-)
>>
>> You got it spot on Heiko. There are a few notes though...
>>
>> As one reuses the existing hardware/IP block, it would be better to
>> avoid copy/pasting code around.
>> Namely:
>>  - (if possible) factor out the exynos g2d kernel functionality to a
>> separate kernel module and wire up the rockhip (via dt ?) to use it
>>  - factor out the g2d specifics out of exynos_drm.h (into
>> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
>> new header
>
> I think the IP blocks themself are quite different between Rockchip's RGA and
> Samsung's g2d and I guess the similarities are more along the lines on how
> that gets integrated into the respective drm driver and userspace.
>
In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
obviously biased, it's better to check how others feel on the topic.

>
>>  - if neither of these are possible, then please ensure that the new
>> header uses correct types (see the docs [1]), use MIT/X11 license (if
>> possible) and link where upstream userspace is happy with the
>> interface (ideally more than a simple test app like libdrm)
>> These might sound like an overkill, although getting UAPI right and
>> maintaining it forever forces us to do so.
>
> As for a real-world usecase, maybe the armsoc xserver might be somewhat easy
> to use. While the core changes I did are in the core project already, I'm
> still keeping the actual Rockchip support separate [0] due to the not-yet-
> resolved create_gem ioctl.
>
> Anyway, the armsoc xserver has some exa implementation hooks were I guess it
> might be relatively easy to hook up soc-specific things.
>
Ouch the armsoc ddx... Last time I've checked it felt like a place
where everyone is doing his own thing, with no actual reviews and/or
maintainer. Iirc most/all of it's functionality was achievable with
modesetting ddx (with or without glamor) ? I take it that things have
changed and/or I misunderstood something ?

Note: The above is not meant as bashing although it hell sure looks like one.

Cheers
Emil

> [0] https://github.com/mmind/xf86-video-armsoc/tree/devel/rockchip
>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-28 21:35             ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-28 21:35 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Yakir Yang, David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	LAKML

On 28 March 2016 at 19:44, Heiko Stübner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org> wrote:
> Am Montag, 28. März 2016, 13:21:02 schrieb Emil Velikov:
>> On 22 March 2016 at 00:42, Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org> wrote:
>> > Hi Yakir,
>> >
>> > Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>> >> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>> >> > Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>> >> >> This patch set would add the RGA direct rendering based 2d graphics
>> >> >> acceleration module.
>> >> >
>> >> > very cool to see that.
>> >>
>> >> ;)
>> >>
>> >> >> This patch set is based on git repository below:
>> >> >> git://people.freedesktop.org/~airlied/linux drm-next
>> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>> >> >>
>> >> >> And the RGA driver is based on Exynos G2D driver, it only manages the
>> >> >> command lists received from user, so user should make the command list
>> >> >> to data and registers needed by operation to use.
>> >> >>
>> >> >> I have prepared an userspace demo application for testing:
>> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
>> >> >>
>> >> >> That is a rockchip libdrm library, and I have write a simple test case
>> >> >> "rockchip_rga_test" that would test the below RGA features:
>> >> >> - solid
>> >> >> - copy
>> >> >> - rotation
>> >> >> - flip
>> >> >> - window clip
>> >> >> - dithering
>> >> >
>> >> > Did you submit your libdrm changes as well?
>> >> >
>> >> > Userspace-interfaces need to be stable so the other side must also get
>> >> > accepted - even before the kernel change if I remember correctly.
>> >>
>> >> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>> >> But I don't find the way to submit patches to libdrm, would you like
>> >> share some helps here ;)
>> >
>> > Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
>> > specific manual on submitting patches.
>> >
>> > But looking at the dri-list archive, dri-devel-PD4FTy7X32lNgt0PjOBp93rCq3LdnpKM@public.gmane.orgrg is
>> > the
>> > right list and looking at the libdrm history it looks like Emil Velikov
>> > <emil.l.velikov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> seems to be doing maintenance-stuff in libdrm.
>> > And as a 3rd recipient, please also include the linux-rockchip list.
>> >
>> > @Emil, please shout if I read that wrong :-)
>>
>> You got it spot on Heiko. There are a few notes though...
>>
>> As one reuses the existing hardware/IP block, it would be better to
>> avoid copy/pasting code around.
>> Namely:
>>  - (if possible) factor out the exynos g2d kernel functionality to a
>> separate kernel module and wire up the rockhip (via dt ?) to use it
>>  - factor out the g2d specifics out of exynos_drm.h (into
>> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
>> new header
>
> I think the IP blocks themself are quite different between Rockchip's RGA and
> Samsung's g2d and I guess the similarities are more along the lines on how
> that gets integrated into the respective drm driver and userspace.
>
In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
obviously biased, it's better to check how others feel on the topic.

>
>>  - if neither of these are possible, then please ensure that the new
>> header uses correct types (see the docs [1]), use MIT/X11 license (if
>> possible) and link where upstream userspace is happy with the
>> interface (ideally more than a simple test app like libdrm)
>> These might sound like an overkill, although getting UAPI right and
>> maintaining it forever forces us to do so.
>
> As for a real-world usecase, maybe the armsoc xserver might be somewhat easy
> to use. While the core changes I did are in the core project already, I'm
> still keeping the actual Rockchip support separate [0] due to the not-yet-
> resolved create_gem ioctl.
>
> Anyway, the armsoc xserver has some exa implementation hooks were I guess it
> might be relatively easy to hook up soc-specific things.
>
Ouch the armsoc ddx... Last time I've checked it felt like a place
where everyone is doing his own thing, with no actual reviews and/or
maintainer. Iirc most/all of it's functionality was achievable with
modesetting ddx (with or without glamor) ? I take it that things have
changed and/or I misunderstood something ?

Note: The above is not meant as bashing although it hell sure looks like one.

Cheers
Emil

> [0] https://github.com/mmind/xf86-video-armsoc/tree/devel/rockchip
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-28 21:35             ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-28 21:35 UTC (permalink / raw)
  To: linux-arm-kernel

On 28 March 2016 at 19:44, Heiko St?bner <heiko@sntech.de> wrote:
> Am Montag, 28. M?rz 2016, 13:21:02 schrieb Emil Velikov:
>> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
>> > Hi Yakir,
>> >
>> > Am Montag, 21. M?rz 2016, 20:17:46 schrieb Yakir Yang:
>> >> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
>> >> > Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
>> >> >> This patch set would add the RGA direct rendering based 2d graphics
>> >> >> acceleration module.
>> >> >
>> >> > very cool to see that.
>> >>
>> >> ;)
>> >>
>> >> >> This patch set is based on git repository below:
>> >> >> git://people.freedesktop.org/~airlied/linux drm-next
>> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>> >> >>
>> >> >> And the RGA driver is based on Exynos G2D driver, it only manages the
>> >> >> command lists received from user, so user should make the command list
>> >> >> to data and registers needed by operation to use.
>> >> >>
>> >> >> I have prepared an userspace demo application for testing:
>> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
>> >> >>
>> >> >> That is a rockchip libdrm library, and I have write a simple test case
>> >> >> "rockchip_rga_test" that would test the below RGA features:
>> >> >> - solid
>> >> >> - copy
>> >> >> - rotation
>> >> >> - flip
>> >> >> - window clip
>> >> >> - dithering
>> >> >
>> >> > Did you submit your libdrm changes as well?
>> >> >
>> >> > Userspace-interfaces need to be stable so the other side must also get
>> >> > accepted - even before the kernel change if I remember correctly.
>> >>
>> >> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>> >> But I don't find the way to submit patches to libdrm, would you like
>> >> share some helps here ;)
>> >
>> > Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
>> > specific manual on submitting patches.
>> >
>> > But looking at the dri-list archive, dri-devel at lists.freedesktop.org is
>> > the
>> > right list and looking at the libdrm history it looks like Emil Velikov
>> > <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
>> > And as a 3rd recipient, please also include the linux-rockchip list.
>> >
>> > @Emil, please shout if I read that wrong :-)
>>
>> You got it spot on Heiko. There are a few notes though...
>>
>> As one reuses the existing hardware/IP block, it would be better to
>> avoid copy/pasting code around.
>> Namely:
>>  - (if possible) factor out the exynos g2d kernel functionality to a
>> separate kernel module and wire up the rockhip (via dt ?) to use it
>>  - factor out the g2d specifics out of exynos_drm.h (into
>> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
>> new header
>
> I think the IP blocks themself are quite different between Rockchip's RGA and
> Samsung's g2d and I guess the similarities are more along the lines on how
> that gets integrated into the respective drm driver and userspace.
>
In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
obviously biased, it's better to check how others feel on the topic.

>
>>  - if neither of these are possible, then please ensure that the new
>> header uses correct types (see the docs [1]), use MIT/X11 license (if
>> possible) and link where upstream userspace is happy with the
>> interface (ideally more than a simple test app like libdrm)
>> These might sound like an overkill, although getting UAPI right and
>> maintaining it forever forces us to do so.
>
> As for a real-world usecase, maybe the armsoc xserver might be somewhat easy
> to use. While the core changes I did are in the core project already, I'm
> still keeping the actual Rockchip support separate [0] due to the not-yet-
> resolved create_gem ioctl.
>
> Anyway, the armsoc xserver has some exa implementation hooks were I guess it
> might be relatively easy to hook up soc-specific things.
>
Ouch the armsoc ddx... Last time I've checked it felt like a place
where everyone is doing his own thing, with no actual reviews and/or
maintainer. Iirc most/all of it's functionality was achievable with
modesetting ddx (with or without glamor) ? I take it that things have
changed and/or I misunderstood something ?

Note: The above is not meant as bashing although it hell sure looks like one.

Cheers
Emil

> [0] https://github.com/mmind/xf86-video-armsoc/tree/devel/rockchip
>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-28 21:46               ` Heiko Stübner
  0 siblings, 0 replies; 73+ messages in thread
From: Heiko Stübner @ 2016-03-28 21:46 UTC (permalink / raw)
  To: Emil Velikov
  Cc: Yakir Yang, David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	linux-kernel, ML dri-devel, linux-rockchip, LAKML

Am Montag, 28. März 2016, 22:35:36 schrieb Emil Velikov:
> On 28 March 2016 at 19:44, Heiko Stübner <heiko@sntech.de> wrote:
> > Am Montag, 28. März 2016, 13:21:02 schrieb Emil Velikov:
> >> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
> >> > Hi Yakir,
> >> > 
> >> > Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
> >> >> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
> >> >> > Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
> >> >> >> This patch set would add the RGA direct rendering based 2d graphics
> >> >> >> acceleration module.
> >> >> > 
> >> >> > very cool to see that.
> >> >> 
> >> >> ;)
> >> >> 
> >> >> >> This patch set is based on git repository below:
> >> >> >> git://people.freedesktop.org/~airlied/linux drm-next
> >> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> >> >> >> 
> >> >> >> And the RGA driver is based on Exynos G2D driver, it only manages
> >> >> >> the
> >> >> >> command lists received from user, so user should make the command
> >> >> >> list
> >> >> >> to data and registers needed by operation to use.
> >> >> >> 
> >> >> >> I have prepared an userspace demo application for testing:
> >> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
> >> >> >> 
> >> >> >> That is a rockchip libdrm library, and I have write a simple test
> >> >> >> case
> >> >> >> "rockchip_rga_test" that would test the below RGA features:
> >> >> >> - solid
> >> >> >> - copy
> >> >> >> - rotation
> >> >> >> - flip
> >> >> >> - window clip
> >> >> >> - dithering
> >> >> > 
> >> >> > Did you submit your libdrm changes as well?
> >> >> > 
> >> >> > Userspace-interfaces need to be stable so the other side must also
> >> >> > get
> >> >> > accepted - even before the kernel change if I remember correctly.
> >> >> 
> >> >> Got it, and I just saw exynos_fimg2d already landed at mainline
> >> >> libdrm.
> >> >> But I don't find the way to submit patches to libdrm, would you like
> >> >> share some helps here ;)
> >> > 
> >> > Looking at the libdrm sources on cgit.freedesktop.org, I did not find
> >> > any
> >> > specific manual on submitting patches.
> >> > 
> >> > But looking at the dri-list archive, dri-devel@lists.freedesktop.org is
> >> > the
> >> > right list and looking at the libdrm history it looks like Emil Velikov
> >> > <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in
> >> > libdrm.
> >> > And as a 3rd recipient, please also include the linux-rockchip list.
> >> > 
> >> > @Emil, please shout if I read that wrong :-)
> >> 
> >> You got it spot on Heiko. There are a few notes though...
> >> 
> >> As one reuses the existing hardware/IP block, it would be better to
> >> avoid copy/pasting code around.
> >> 
> >> Namely:
> >>  - (if possible) factor out the exynos g2d kernel functionality to a
> >> 
> >> separate kernel module and wire up the rockhip (via dt ?) to use it
> >> 
> >>  - factor out the g2d specifics out of exynos_drm.h (into
> >> 
> >> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
> >> new header
> > 
> > I think the IP blocks themself are quite different between Rockchip's RGA
> > and Samsung's g2d and I guess the similarities are more along the lines
> > on how that gets integrated into the respective drm driver and userspace.
> In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
> obviously biased, it's better to check how others feel on the topic.
> 
> >>  - if neither of these are possible, then please ensure that the new
> >> 
> >> header uses correct types (see the docs [1]), use MIT/X11 license (if
> >> possible) and link where upstream userspace is happy with the
> >> interface (ideally more than a simple test app like libdrm)
> >> These might sound like an overkill, although getting UAPI right and
> >> maintaining it forever forces us to do so.
> > 
> > As for a real-world usecase, maybe the armsoc xserver might be somewhat
> > easy to use. While the core changes I did are in the core project
> > already, I'm still keeping the actual Rockchip support separate [0] due
> > to the not-yet- resolved create_gem ioctl.
> > 
> > Anyway, the armsoc xserver has some exa implementation hooks were I guess
> > it might be relatively easy to hook up soc-specific things.
> 
> Ouch the armsoc ddx... Last time I've checked it felt like a place
> where everyone is doing his own thing, with no actual reviews and/or
> maintainer.

The development rate is pretty low and maintainership is unclear but the per-
soc voodoo is quite limited to the GEM-creation and everything else seems 
somewhat nice when compared for example to the older versions of the ddx.


> Iirc most/all of it's functionality was achievable with
> modesetting ddx (with or without glamor) ? I take it that things have
> changed and/or I misunderstood something ?

I don't really understand that whole stack or how xservers work on a whole ;-)
I was merely able to make the _binary_ mali-driver work with this one and 
remembered that there were hooks for future per-soc exa functions.

I guess for that glamor thing you'd need an actual gpu driver and not that 
libGL-override voodoo those crazy binary drivers do.

At least the modesetting ddx didn't like mali-binary-driver.


Heiko

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-28 21:46               ` Heiko Stübner
  0 siblings, 0 replies; 73+ messages in thread
From: Heiko Stübner @ 2016-03-28 21:46 UTC (permalink / raw)
  To: Emil Velikov
  Cc: Yakir Yang, David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, ML dri-devel,
	linux-rockchip, LAKML

Am Montag, 28. März 2016, 22:35:36 schrieb Emil Velikov:
> On 28 March 2016 at 19:44, Heiko Stübner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org> wrote:
> > Am Montag, 28. März 2016, 13:21:02 schrieb Emil Velikov:
> >> On 22 March 2016 at 00:42, Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org> wrote:
> >> > Hi Yakir,
> >> > 
> >> > Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
> >> >> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
> >> >> > Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
> >> >> >> This patch set would add the RGA direct rendering based 2d graphics
> >> >> >> acceleration module.
> >> >> > 
> >> >> > very cool to see that.
> >> >> 
> >> >> ;)
> >> >> 
> >> >> >> This patch set is based on git repository below:
> >> >> >> git://people.freedesktop.org/~airlied/linux drm-next
> >> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> >> >> >> 
> >> >> >> And the RGA driver is based on Exynos G2D driver, it only manages
> >> >> >> the
> >> >> >> command lists received from user, so user should make the command
> >> >> >> list
> >> >> >> to data and registers needed by operation to use.
> >> >> >> 
> >> >> >> I have prepared an userspace demo application for testing:
> >> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
> >> >> >> 
> >> >> >> That is a rockchip libdrm library, and I have write a simple test
> >> >> >> case
> >> >> >> "rockchip_rga_test" that would test the below RGA features:
> >> >> >> - solid
> >> >> >> - copy
> >> >> >> - rotation
> >> >> >> - flip
> >> >> >> - window clip
> >> >> >> - dithering
> >> >> > 
> >> >> > Did you submit your libdrm changes as well?
> >> >> > 
> >> >> > Userspace-interfaces need to be stable so the other side must also
> >> >> > get
> >> >> > accepted - even before the kernel change if I remember correctly.
> >> >> 
> >> >> Got it, and I just saw exynos_fimg2d already landed at mainline
> >> >> libdrm.
> >> >> But I don't find the way to submit patches to libdrm, would you like
> >> >> share some helps here ;)
> >> > 
> >> > Looking at the libdrm sources on cgit.freedesktop.org, I did not find
> >> > any
> >> > specific manual on submitting patches.
> >> > 
> >> > But looking at the dri-list archive, dri-devel-PD4FTy7X32lNgt0PjOBp93gSJqDPrsil@public.gmane.org.org is
> >> > the
> >> > right list and looking at the libdrm history it looks like Emil Velikov
> >> > <emil.l.velikov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> seems to be doing maintenance-stuff in
> >> > libdrm.
> >> > And as a 3rd recipient, please also include the linux-rockchip list.
> >> > 
> >> > @Emil, please shout if I read that wrong :-)
> >> 
> >> You got it spot on Heiko. There are a few notes though...
> >> 
> >> As one reuses the existing hardware/IP block, it would be better to
> >> avoid copy/pasting code around.
> >> 
> >> Namely:
> >>  - (if possible) factor out the exynos g2d kernel functionality to a
> >> 
> >> separate kernel module and wire up the rockhip (via dt ?) to use it
> >> 
> >>  - factor out the g2d specifics out of exynos_drm.h (into
> >> 
> >> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
> >> new header
> > 
> > I think the IP blocks themself are quite different between Rockchip's RGA
> > and Samsung's g2d and I guess the similarities are more along the lines
> > on how that gets integrated into the respective drm driver and userspace.
> In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
> obviously biased, it's better to check how others feel on the topic.
> 
> >>  - if neither of these are possible, then please ensure that the new
> >> 
> >> header uses correct types (see the docs [1]), use MIT/X11 license (if
> >> possible) and link where upstream userspace is happy with the
> >> interface (ideally more than a simple test app like libdrm)
> >> These might sound like an overkill, although getting UAPI right and
> >> maintaining it forever forces us to do so.
> > 
> > As for a real-world usecase, maybe the armsoc xserver might be somewhat
> > easy to use. While the core changes I did are in the core project
> > already, I'm still keeping the actual Rockchip support separate [0] due
> > to the not-yet- resolved create_gem ioctl.
> > 
> > Anyway, the armsoc xserver has some exa implementation hooks were I guess
> > it might be relatively easy to hook up soc-specific things.
> 
> Ouch the armsoc ddx... Last time I've checked it felt like a place
> where everyone is doing his own thing, with no actual reviews and/or
> maintainer.

The development rate is pretty low and maintainership is unclear but the per-
soc voodoo is quite limited to the GEM-creation and everything else seems 
somewhat nice when compared for example to the older versions of the ddx.


> Iirc most/all of it's functionality was achievable with
> modesetting ddx (with or without glamor) ? I take it that things have
> changed and/or I misunderstood something ?

I don't really understand that whole stack or how xservers work on a whole ;-)
I was merely able to make the _binary_ mali-driver work with this one and 
remembered that there were hooks for future per-soc exa functions.

I guess for that glamor thing you'd need an actual gpu driver and not that 
libGL-override voodoo those crazy binary drivers do.

At least the modesetting ddx didn't like mali-binary-driver.


Heiko
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-28 21:46               ` Heiko Stübner
  0 siblings, 0 replies; 73+ messages in thread
From: Heiko Stübner @ 2016-03-28 21:46 UTC (permalink / raw)
  To: linux-arm-kernel

Am Montag, 28. M?rz 2016, 22:35:36 schrieb Emil Velikov:
> On 28 March 2016 at 19:44, Heiko St?bner <heiko@sntech.de> wrote:
> > Am Montag, 28. M?rz 2016, 13:21:02 schrieb Emil Velikov:
> >> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
> >> > Hi Yakir,
> >> > 
> >> > Am Montag, 21. M?rz 2016, 20:17:46 schrieb Yakir Yang:
> >> >> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
> >> >> > Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
> >> >> >> This patch set would add the RGA direct rendering based 2d graphics
> >> >> >> acceleration module.
> >> >> > 
> >> >> > very cool to see that.
> >> >> 
> >> >> ;)
> >> >> 
> >> >> >> This patch set is based on git repository below:
> >> >> >> git://people.freedesktop.org/~airlied/linux drm-next
> >> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> >> >> >> 
> >> >> >> And the RGA driver is based on Exynos G2D driver, it only manages
> >> >> >> the
> >> >> >> command lists received from user, so user should make the command
> >> >> >> list
> >> >> >> to data and registers needed by operation to use.
> >> >> >> 
> >> >> >> I have prepared an userspace demo application for testing:
> >> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
> >> >> >> 
> >> >> >> That is a rockchip libdrm library, and I have write a simple test
> >> >> >> case
> >> >> >> "rockchip_rga_test" that would test the below RGA features:
> >> >> >> - solid
> >> >> >> - copy
> >> >> >> - rotation
> >> >> >> - flip
> >> >> >> - window clip
> >> >> >> - dithering
> >> >> > 
> >> >> > Did you submit your libdrm changes as well?
> >> >> > 
> >> >> > Userspace-interfaces need to be stable so the other side must also
> >> >> > get
> >> >> > accepted - even before the kernel change if I remember correctly.
> >> >> 
> >> >> Got it, and I just saw exynos_fimg2d already landed at mainline
> >> >> libdrm.
> >> >> But I don't find the way to submit patches to libdrm, would you like
> >> >> share some helps here ;)
> >> > 
> >> > Looking at the libdrm sources on cgit.freedesktop.org, I did not find
> >> > any
> >> > specific manual on submitting patches.
> >> > 
> >> > But looking at the dri-list archive, dri-devel at lists.freedesktop.org is
> >> > the
> >> > right list and looking at the libdrm history it looks like Emil Velikov
> >> > <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in
> >> > libdrm.
> >> > And as a 3rd recipient, please also include the linux-rockchip list.
> >> > 
> >> > @Emil, please shout if I read that wrong :-)
> >> 
> >> You got it spot on Heiko. There are a few notes though...
> >> 
> >> As one reuses the existing hardware/IP block, it would be better to
> >> avoid copy/pasting code around.
> >> 
> >> Namely:
> >>  - (if possible) factor out the exynos g2d kernel functionality to a
> >> 
> >> separate kernel module and wire up the rockhip (via dt ?) to use it
> >> 
> >>  - factor out the g2d specifics out of exynos_drm.h (into
> >> 
> >> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
> >> new header
> > 
> > I think the IP blocks themself are quite different between Rockchip's RGA
> > and Samsung's g2d and I guess the similarities are more along the lines
> > on how that gets integrated into the respective drm driver and userspace.
> In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
> obviously biased, it's better to check how others feel on the topic.
> 
> >>  - if neither of these are possible, then please ensure that the new
> >> 
> >> header uses correct types (see the docs [1]), use MIT/X11 license (if
> >> possible) and link where upstream userspace is happy with the
> >> interface (ideally more than a simple test app like libdrm)
> >> These might sound like an overkill, although getting UAPI right and
> >> maintaining it forever forces us to do so.
> > 
> > As for a real-world usecase, maybe the armsoc xserver might be somewhat
> > easy to use. While the core changes I did are in the core project
> > already, I'm still keeping the actual Rockchip support separate [0] due
> > to the not-yet- resolved create_gem ioctl.
> > 
> > Anyway, the armsoc xserver has some exa implementation hooks were I guess
> > it might be relatively easy to hook up soc-specific things.
> 
> Ouch the armsoc ddx... Last time I've checked it felt like a place
> where everyone is doing his own thing, with no actual reviews and/or
> maintainer.

The development rate is pretty low and maintainership is unclear but the per-
soc voodoo is quite limited to the GEM-creation and everything else seems 
somewhat nice when compared for example to the older versions of the ddx.


> Iirc most/all of it's functionality was achievable with
> modesetting ddx (with or without glamor) ? I take it that things have
> changed and/or I misunderstood something ?

I don't really understand that whole stack or how xservers work on a whole ;-)
I was merely able to make the _binary_ mali-driver work with this one and 
remembered that there were hooks for future per-soc exa functions.

I guess for that glamor thing you'd need an actual gpu driver and not that 
libGL-override voodoo those crazy binary drivers do.

At least the modesetting ddx didn't like mali-binary-driver.


Heiko

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-28 21:46               ` Heiko Stübner
  (?)
@ 2016-03-28 22:07                 ` Emil Velikov
  -1 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-28 22:07 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Yakir Yang, David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	LAKML

On 28 March 2016 at 22:46, Heiko Stübner <heiko@sntech.de> wrote:
> Am Montag, 28. März 2016, 22:35:36 schrieb Emil Velikov:
>> On 28 March 2016 at 19:44, Heiko Stübner <heiko@sntech.de> wrote:
>> > Am Montag, 28. März 2016, 13:21:02 schrieb Emil Velikov:
>> >> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
>> >> > Hi Yakir,
>> >> >
>> >> > Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>> >> >> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>> >> >> > Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>> >> >> >> This patch set would add the RGA direct rendering based 2d graphics
>> >> >> >> acceleration module.
>> >> >> >
>> >> >> > very cool to see that.
>> >> >>
>> >> >> ;)
>> >> >>
>> >> >> >> This patch set is based on git repository below:
>> >> >> >> git://people.freedesktop.org/~airlied/linux drm-next
>> >> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>> >> >> >>
>> >> >> >> And the RGA driver is based on Exynos G2D driver, it only manages
>> >> >> >> the
>> >> >> >> command lists received from user, so user should make the command
>> >> >> >> list
>> >> >> >> to data and registers needed by operation to use.
>> >> >> >>
>> >> >> >> I have prepared an userspace demo application for testing:
>> >> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
>> >> >> >>
>> >> >> >> That is a rockchip libdrm library, and I have write a simple test
>> >> >> >> case
>> >> >> >> "rockchip_rga_test" that would test the below RGA features:
>> >> >> >> - solid
>> >> >> >> - copy
>> >> >> >> - rotation
>> >> >> >> - flip
>> >> >> >> - window clip
>> >> >> >> - dithering
>> >> >> >
>> >> >> > Did you submit your libdrm changes as well?
>> >> >> >
>> >> >> > Userspace-interfaces need to be stable so the other side must also
>> >> >> > get
>> >> >> > accepted - even before the kernel change if I remember correctly.
>> >> >>
>> >> >> Got it, and I just saw exynos_fimg2d already landed at mainline
>> >> >> libdrm.
>> >> >> But I don't find the way to submit patches to libdrm, would you like
>> >> >> share some helps here ;)
>> >> >
>> >> > Looking at the libdrm sources on cgit.freedesktop.org, I did not find
>> >> > any
>> >> > specific manual on submitting patches.
>> >> >
>> >> > But looking at the dri-list archive, dri-devel@lists.freedesktop.org is
>> >> > the
>> >> > right list and looking at the libdrm history it looks like Emil Velikov
>> >> > <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in
>> >> > libdrm.
>> >> > And as a 3rd recipient, please also include the linux-rockchip list.
>> >> >
>> >> > @Emil, please shout if I read that wrong :-)
>> >>
>> >> You got it spot on Heiko. There are a few notes though...
>> >>
>> >> As one reuses the existing hardware/IP block, it would be better to
>> >> avoid copy/pasting code around.
>> >>
>> >> Namely:
>> >>  - (if possible) factor out the exynos g2d kernel functionality to a
>> >>
>> >> separate kernel module and wire up the rockhip (via dt ?) to use it
>> >>
>> >>  - factor out the g2d specifics out of exynos_drm.h (into
>> >>
>> >> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
>> >> new header
>> >
>> > I think the IP blocks themself are quite different between Rockchip's RGA
>> > and Samsung's g2d and I guess the similarities are more along the lines
>> > on how that gets integrated into the respective drm driver and userspace.
>> In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
>> obviously biased, it's better to check how others feel on the topic.
>>
>> >>  - if neither of these are possible, then please ensure that the new
>> >>
>> >> header uses correct types (see the docs [1]), use MIT/X11 license (if
>> >> possible) and link where upstream userspace is happy with the
>> >> interface (ideally more than a simple test app like libdrm)
>> >> These might sound like an overkill, although getting UAPI right and
>> >> maintaining it forever forces us to do so.
>> >
>> > As for a real-world usecase, maybe the armsoc xserver might be somewhat
>> > easy to use. While the core changes I did are in the core project
>> > already, I'm still keeping the actual Rockchip support separate [0] due
>> > to the not-yet- resolved create_gem ioctl.
>> >
>> > Anyway, the armsoc xserver has some exa implementation hooks were I guess
>> > it might be relatively easy to hook up soc-specific things.
>>
>> Ouch the armsoc ddx... Last time I've checked it felt like a place
>> where everyone is doing his own thing, with no actual reviews and/or
>> maintainer.
>
> The development rate is pretty low and maintainership is unclear but the per-
> soc voodoo is quite limited to the GEM-creation and everything else seems
> somewhat nice when compared for example to the older versions of the ddx.
>
>
>> Iirc most/all of it's functionality was achievable with
>> modesetting ddx (with or without glamor) ? I take it that things have
>> changed and/or I misunderstood something ?
>
> I don't really understand that whole stack or how xservers work on a whole ;-)
> I was merely able to make the _binary_ mali-driver work with this one and
> remembered that there were hooks for future per-soc exa functions.
>
> I guess for that glamor thing you'd need an actual gpu driver and not that
> libGL-override voodoo those crazy binary drivers do.
>
> At least the modesetting ddx didn't like mali-binary-driver.
>
A quick rundown of the whole thing (simplified and maybe slightly off)
- the modesetting DDX (merged in xserver for a few releases now),
relies on GBM for buffer management and GL{,ES} for acceleration. On
the KMS side it's as generic as any other driver should be.

I'm not sure how well modesetting works without gbm, but it should be
able to build at least. About getting it (or others) to work with
binary blobs... I guess you know what my and others' view is. Place
the fact that one tries to upstream a kernel interface which,
indirectly, interacts with such a module makes things even more ...
lovely.

Sorry to be the bearer of bad news. If you have other ideas or others
feels like I'm overly dramatic let me know, please.

-Emil

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-28 22:07                 ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-28 22:07 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: devicetree, Russell King, Pawel Moll, Ian Campbell,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	Rob Herring, Kumar Gala, LAKML

On 28 March 2016 at 22:46, Heiko Stübner <heiko@sntech.de> wrote:
> Am Montag, 28. März 2016, 22:35:36 schrieb Emil Velikov:
>> On 28 March 2016 at 19:44, Heiko Stübner <heiko@sntech.de> wrote:
>> > Am Montag, 28. März 2016, 13:21:02 schrieb Emil Velikov:
>> >> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
>> >> > Hi Yakir,
>> >> >
>> >> > Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>> >> >> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>> >> >> > Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>> >> >> >> This patch set would add the RGA direct rendering based 2d graphics
>> >> >> >> acceleration module.
>> >> >> >
>> >> >> > very cool to see that.
>> >> >>
>> >> >> ;)
>> >> >>
>> >> >> >> This patch set is based on git repository below:
>> >> >> >> git://people.freedesktop.org/~airlied/linux drm-next
>> >> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>> >> >> >>
>> >> >> >> And the RGA driver is based on Exynos G2D driver, it only manages
>> >> >> >> the
>> >> >> >> command lists received from user, so user should make the command
>> >> >> >> list
>> >> >> >> to data and registers needed by operation to use.
>> >> >> >>
>> >> >> >> I have prepared an userspace demo application for testing:
>> >> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
>> >> >> >>
>> >> >> >> That is a rockchip libdrm library, and I have write a simple test
>> >> >> >> case
>> >> >> >> "rockchip_rga_test" that would test the below RGA features:
>> >> >> >> - solid
>> >> >> >> - copy
>> >> >> >> - rotation
>> >> >> >> - flip
>> >> >> >> - window clip
>> >> >> >> - dithering
>> >> >> >
>> >> >> > Did you submit your libdrm changes as well?
>> >> >> >
>> >> >> > Userspace-interfaces need to be stable so the other side must also
>> >> >> > get
>> >> >> > accepted - even before the kernel change if I remember correctly.
>> >> >>
>> >> >> Got it, and I just saw exynos_fimg2d already landed at mainline
>> >> >> libdrm.
>> >> >> But I don't find the way to submit patches to libdrm, would you like
>> >> >> share some helps here ;)
>> >> >
>> >> > Looking at the libdrm sources on cgit.freedesktop.org, I did not find
>> >> > any
>> >> > specific manual on submitting patches.
>> >> >
>> >> > But looking at the dri-list archive, dri-devel@lists.freedesktop.org is
>> >> > the
>> >> > right list and looking at the libdrm history it looks like Emil Velikov
>> >> > <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in
>> >> > libdrm.
>> >> > And as a 3rd recipient, please also include the linux-rockchip list.
>> >> >
>> >> > @Emil, please shout if I read that wrong :-)
>> >>
>> >> You got it spot on Heiko. There are a few notes though...
>> >>
>> >> As one reuses the existing hardware/IP block, it would be better to
>> >> avoid copy/pasting code around.
>> >>
>> >> Namely:
>> >>  - (if possible) factor out the exynos g2d kernel functionality to a
>> >>
>> >> separate kernel module and wire up the rockhip (via dt ?) to use it
>> >>
>> >>  - factor out the g2d specifics out of exynos_drm.h (into
>> >>
>> >> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
>> >> new header
>> >
>> > I think the IP blocks themself are quite different between Rockchip's RGA
>> > and Samsung's g2d and I guess the similarities are more along the lines
>> > on how that gets integrated into the respective drm driver and userspace.
>> In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
>> obviously biased, it's better to check how others feel on the topic.
>>
>> >>  - if neither of these are possible, then please ensure that the new
>> >>
>> >> header uses correct types (see the docs [1]), use MIT/X11 license (if
>> >> possible) and link where upstream userspace is happy with the
>> >> interface (ideally more than a simple test app like libdrm)
>> >> These might sound like an overkill, although getting UAPI right and
>> >> maintaining it forever forces us to do so.
>> >
>> > As for a real-world usecase, maybe the armsoc xserver might be somewhat
>> > easy to use. While the core changes I did are in the core project
>> > already, I'm still keeping the actual Rockchip support separate [0] due
>> > to the not-yet- resolved create_gem ioctl.
>> >
>> > Anyway, the armsoc xserver has some exa implementation hooks were I guess
>> > it might be relatively easy to hook up soc-specific things.
>>
>> Ouch the armsoc ddx... Last time I've checked it felt like a place
>> where everyone is doing his own thing, with no actual reviews and/or
>> maintainer.
>
> The development rate is pretty low and maintainership is unclear but the per-
> soc voodoo is quite limited to the GEM-creation and everything else seems
> somewhat nice when compared for example to the older versions of the ddx.
>
>
>> Iirc most/all of it's functionality was achievable with
>> modesetting ddx (with or without glamor) ? I take it that things have
>> changed and/or I misunderstood something ?
>
> I don't really understand that whole stack or how xservers work on a whole ;-)
> I was merely able to make the _binary_ mali-driver work with this one and
> remembered that there were hooks for future per-soc exa functions.
>
> I guess for that glamor thing you'd need an actual gpu driver and not that
> libGL-override voodoo those crazy binary drivers do.
>
> At least the modesetting ddx didn't like mali-binary-driver.
>
A quick rundown of the whole thing (simplified and maybe slightly off)
- the modesetting DDX (merged in xserver for a few releases now),
relies on GBM for buffer management and GL{,ES} for acceleration. On
the KMS side it's as generic as any other driver should be.

I'm not sure how well modesetting works without gbm, but it should be
able to build at least. About getting it (or others) to work with
binary blobs... I guess you know what my and others' view is. Place
the fact that one tries to upstream a kernel interface which,
indirectly, interacts with such a module makes things even more ...
lovely.

Sorry to be the bearer of bad news. If you have other ideas or others
feels like I'm overly dramatic let me know, please.

-Emil
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-28 22:07                 ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-28 22:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 28 March 2016 at 22:46, Heiko St?bner <heiko@sntech.de> wrote:
> Am Montag, 28. M?rz 2016, 22:35:36 schrieb Emil Velikov:
>> On 28 March 2016 at 19:44, Heiko St?bner <heiko@sntech.de> wrote:
>> > Am Montag, 28. M?rz 2016, 13:21:02 schrieb Emil Velikov:
>> >> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
>> >> > Hi Yakir,
>> >> >
>> >> > Am Montag, 21. M?rz 2016, 20:17:46 schrieb Yakir Yang:
>> >> >> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
>> >> >> > Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
>> >> >> >> This patch set would add the RGA direct rendering based 2d graphics
>> >> >> >> acceleration module.
>> >> >> >
>> >> >> > very cool to see that.
>> >> >>
>> >> >> ;)
>> >> >>
>> >> >> >> This patch set is based on git repository below:
>> >> >> >> git://people.freedesktop.org/~airlied/linux drm-next
>> >> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>> >> >> >>
>> >> >> >> And the RGA driver is based on Exynos G2D driver, it only manages
>> >> >> >> the
>> >> >> >> command lists received from user, so user should make the command
>> >> >> >> list
>> >> >> >> to data and registers needed by operation to use.
>> >> >> >>
>> >> >> >> I have prepared an userspace demo application for testing:
>> >> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
>> >> >> >>
>> >> >> >> That is a rockchip libdrm library, and I have write a simple test
>> >> >> >> case
>> >> >> >> "rockchip_rga_test" that would test the below RGA features:
>> >> >> >> - solid
>> >> >> >> - copy
>> >> >> >> - rotation
>> >> >> >> - flip
>> >> >> >> - window clip
>> >> >> >> - dithering
>> >> >> >
>> >> >> > Did you submit your libdrm changes as well?
>> >> >> >
>> >> >> > Userspace-interfaces need to be stable so the other side must also
>> >> >> > get
>> >> >> > accepted - even before the kernel change if I remember correctly.
>> >> >>
>> >> >> Got it, and I just saw exynos_fimg2d already landed at mainline
>> >> >> libdrm.
>> >> >> But I don't find the way to submit patches to libdrm, would you like
>> >> >> share some helps here ;)
>> >> >
>> >> > Looking at the libdrm sources on cgit.freedesktop.org, I did not find
>> >> > any
>> >> > specific manual on submitting patches.
>> >> >
>> >> > But looking at the dri-list archive, dri-devel at lists.freedesktop.org is
>> >> > the
>> >> > right list and looking at the libdrm history it looks like Emil Velikov
>> >> > <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in
>> >> > libdrm.
>> >> > And as a 3rd recipient, please also include the linux-rockchip list.
>> >> >
>> >> > @Emil, please shout if I read that wrong :-)
>> >>
>> >> You got it spot on Heiko. There are a few notes though...
>> >>
>> >> As one reuses the existing hardware/IP block, it would be better to
>> >> avoid copy/pasting code around.
>> >>
>> >> Namely:
>> >>  - (if possible) factor out the exynos g2d kernel functionality to a
>> >>
>> >> separate kernel module and wire up the rockhip (via dt ?) to use it
>> >>
>> >>  - factor out the g2d specifics out of exynos_drm.h (into
>> >>
>> >> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
>> >> new header
>> >
>> > I think the IP blocks themself are quite different between Rockchip's RGA
>> > and Samsung's g2d and I guess the similarities are more along the lines
>> > on how that gets integrated into the respective drm driver and userspace.
>> In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
>> obviously biased, it's better to check how others feel on the topic.
>>
>> >>  - if neither of these are possible, then please ensure that the new
>> >>
>> >> header uses correct types (see the docs [1]), use MIT/X11 license (if
>> >> possible) and link where upstream userspace is happy with the
>> >> interface (ideally more than a simple test app like libdrm)
>> >> These might sound like an overkill, although getting UAPI right and
>> >> maintaining it forever forces us to do so.
>> >
>> > As for a real-world usecase, maybe the armsoc xserver might be somewhat
>> > easy to use. While the core changes I did are in the core project
>> > already, I'm still keeping the actual Rockchip support separate [0] due
>> > to the not-yet- resolved create_gem ioctl.
>> >
>> > Anyway, the armsoc xserver has some exa implementation hooks were I guess
>> > it might be relatively easy to hook up soc-specific things.
>>
>> Ouch the armsoc ddx... Last time I've checked it felt like a place
>> where everyone is doing his own thing, with no actual reviews and/or
>> maintainer.
>
> The development rate is pretty low and maintainership is unclear but the per-
> soc voodoo is quite limited to the GEM-creation and everything else seems
> somewhat nice when compared for example to the older versions of the ddx.
>
>
>> Iirc most/all of it's functionality was achievable with
>> modesetting ddx (with or without glamor) ? I take it that things have
>> changed and/or I misunderstood something ?
>
> I don't really understand that whole stack or how xservers work on a whole ;-)
> I was merely able to make the _binary_ mali-driver work with this one and
> remembered that there were hooks for future per-soc exa functions.
>
> I guess for that glamor thing you'd need an actual gpu driver and not that
> libGL-override voodoo those crazy binary drivers do.
>
> At least the modesetting ddx didn't like mali-binary-driver.
>
A quick rundown of the whole thing (simplified and maybe slightly off)
- the modesetting DDX (merged in xserver for a few releases now),
relies on GBM for buffer management and GL{,ES} for acceleration. On
the KMS side it's as generic as any other driver should be.

I'm not sure how well modesetting works without gbm, but it should be
able to build at least. About getting it (or others) to work with
binary blobs... I guess you know what my and others' view is. Place
the fact that one tries to upstream a kernel interface which,
indirectly, interacts with such a module makes things even more ...
lovely.

Sorry to be the bearer of bad news. If you have other ideas or others
feels like I'm overly dramatic let me know, please.

-Emil

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-28 22:07                 ` Emil Velikov
@ 2016-03-28 22:13                   ` Heiko Stübner
  -1 siblings, 0 replies; 73+ messages in thread
From: Heiko Stübner @ 2016-03-28 22:13 UTC (permalink / raw)
  To: Emil Velikov
  Cc: Yakir Yang, David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	linux-kernel, ML dri-devel, linux-rockchip, LAKML

Am Montag, 28. März 2016, 23:07:59 schrieb Emil Velikov:
> On 28 March 2016 at 22:46, Heiko Stübner <heiko@sntech.de> wrote:
> > Am Montag, 28. März 2016, 22:35:36 schrieb Emil Velikov:
> >> On 28 March 2016 at 19:44, Heiko Stübner <heiko@sntech.de> wrote:
> >> > Am Montag, 28. März 2016, 13:21:02 schrieb Emil Velikov:
> >> >> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
> >> >> > Hi Yakir,
> >> >> > 
> >> >> > Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
> >> >> >> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
> >> >> >> > Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
> >> >> >> >> This patch set would add the RGA direct rendering based 2d
> >> >> >> >> graphics
> >> >> >> >> acceleration module.
> >> >> >> > 
> >> >> >> > very cool to see that.
> >> >> >> 
> >> >> >> ;)
> >> >> >> 
> >> >> >> >> This patch set is based on git repository below:
> >> >> >> >> git://people.freedesktop.org/~airlied/linux drm-next
> >> >> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> >> >> >> >> 
> >> >> >> >> And the RGA driver is based on Exynos G2D driver, it only
> >> >> >> >> manages
> >> >> >> >> the
> >> >> >> >> command lists received from user, so user should make the
> >> >> >> >> command
> >> >> >> >> list
> >> >> >> >> to data and registers needed by operation to use.
> >> >> >> >> 
> >> >> >> >> I have prepared an userspace demo application for testing:
> >> >> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
> >> >> >> >> 
> >> >> >> >> That is a rockchip libdrm library, and I have write a simple
> >> >> >> >> test
> >> >> >> >> case
> >> >> >> >> "rockchip_rga_test" that would test the below RGA features:
> >> >> >> >> - solid
> >> >> >> >> - copy
> >> >> >> >> - rotation
> >> >> >> >> - flip
> >> >> >> >> - window clip
> >> >> >> >> - dithering
> >> >> >> > 
> >> >> >> > Did you submit your libdrm changes as well?
> >> >> >> > 
> >> >> >> > Userspace-interfaces need to be stable so the other side must
> >> >> >> > also
> >> >> >> > get
> >> >> >> > accepted - even before the kernel change if I remember correctly.
> >> >> >> 
> >> >> >> Got it, and I just saw exynos_fimg2d already landed at mainline
> >> >> >> libdrm.
> >> >> >> But I don't find the way to submit patches to libdrm, would you
> >> >> >> like
> >> >> >> share some helps here ;)
> >> >> > 
> >> >> > Looking at the libdrm sources on cgit.freedesktop.org, I did not
> >> >> > find
> >> >> > any
> >> >> > specific manual on submitting patches.
> >> >> > 
> >> >> > But looking at the dri-list archive, dri-devel@lists.freedesktop.org
> >> >> > is
> >> >> > the
> >> >> > right list and looking at the libdrm history it looks like Emil
> >> >> > Velikov
> >> >> > <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in
> >> >> > libdrm.
> >> >> > And as a 3rd recipient, please also include the linux-rockchip list.
> >> >> > 
> >> >> > @Emil, please shout if I read that wrong :-)
> >> >> 
> >> >> You got it spot on Heiko. There are a few notes though...
> >> >> 
> >> >> As one reuses the existing hardware/IP block, it would be better to
> >> >> avoid copy/pasting code around.
> >> >> 
> >> >> Namely:
> >> >>  - (if possible) factor out the exynos g2d kernel functionality to a
> >> >> 
> >> >> separate kernel module and wire up the rockhip (via dt ?) to use it
> >> >> 
> >> >>  - factor out the g2d specifics out of exynos_drm.h (into
> >> >> 
> >> >> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
> >> >> new header
> >> > 
> >> > I think the IP blocks themself are quite different between Rockchip's
> >> > RGA
> >> > and Samsung's g2d and I guess the similarities are more along the lines
> >> > on how that gets integrated into the respective drm driver and
> >> > userspace.
> >> 
> >> In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
> >> obviously biased, it's better to check how others feel on the topic.
> >> 
> >> >>  - if neither of these are possible, then please ensure that the new
> >> >> 
> >> >> header uses correct types (see the docs [1]), use MIT/X11 license (if
> >> >> possible) and link where upstream userspace is happy with the
> >> >> interface (ideally more than a simple test app like libdrm)
> >> >> These might sound like an overkill, although getting UAPI right and
> >> >> maintaining it forever forces us to do so.
> >> > 
> >> > As for a real-world usecase, maybe the armsoc xserver might be somewhat
> >> > easy to use. While the core changes I did are in the core project
> >> > already, I'm still keeping the actual Rockchip support separate [0] due
> >> > to the not-yet- resolved create_gem ioctl.
> >> > 
> >> > Anyway, the armsoc xserver has some exa implementation hooks were I
> >> > guess
> >> > it might be relatively easy to hook up soc-specific things.
> >> 
> >> Ouch the armsoc ddx... Last time I've checked it felt like a place
> >> where everyone is doing his own thing, with no actual reviews and/or
> >> maintainer.
> > 
> > The development rate is pretty low and maintainership is unclear but the
> > per- soc voodoo is quite limited to the GEM-creation and everything else
> > seems somewhat nice when compared for example to the older versions of
> > the ddx.> 
> >> Iirc most/all of it's functionality was achievable with
> >> modesetting ddx (with or without glamor) ? I take it that things have
> >> changed and/or I misunderstood something ?
> > 
> > I don't really understand that whole stack or how xservers work on a whole
> > ;-) I was merely able to make the _binary_ mali-driver work with this one
> > and remembered that there were hooks for future per-soc exa functions.
> > 
> > I guess for that glamor thing you'd need an actual gpu driver and not that
> > libGL-override voodoo those crazy binary drivers do.
> > 
> > At least the modesetting ddx didn't like mali-binary-driver.
> 
> A quick rundown of the whole thing (simplified and maybe slightly off)
> - the modesetting DDX (merged in xserver for a few releases now),
> relies on GBM for buffer management and GL{,ES} for acceleration. On
> the KMS side it's as generic as any other driver should be.
> 
> I'm not sure how well modesetting works without gbm, but it should be
> able to build at least. About getting it (or others) to work with
> binary blobs... I guess you know what my and others' view is. Place
> the fact that one tries to upstream a kernel interface which,
> indirectly, interacts with such a module makes things even more ...
> lovely.
> 
> Sorry to be the bearer of bad news. If you have other ideas or others
> feels like I'm overly dramatic let me know, please.

I have the feeling we're going quite a bit off-topic right now :-) .
The binary-driver-crazyness, hasn't really anything to do with Yakir's support 
for the RGA (which is about raster-graphics-acceleration, so 2d stuff).

And me mentioning the armsoc-ddx was merely a means to allow some sort of 
different userspace user, as requested in your original mail ;-) .

Maybe you know a better use-case on where to demonstrate the viability of the 
userspace API for it as originally requested.

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-28 22:13                   ` Heiko Stübner
  0 siblings, 0 replies; 73+ messages in thread
From: Heiko Stübner @ 2016-03-28 22:13 UTC (permalink / raw)
  To: linux-arm-kernel

Am Montag, 28. M?rz 2016, 23:07:59 schrieb Emil Velikov:
> On 28 March 2016 at 22:46, Heiko St?bner <heiko@sntech.de> wrote:
> > Am Montag, 28. M?rz 2016, 22:35:36 schrieb Emil Velikov:
> >> On 28 March 2016 at 19:44, Heiko St?bner <heiko@sntech.de> wrote:
> >> > Am Montag, 28. M?rz 2016, 13:21:02 schrieb Emil Velikov:
> >> >> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
> >> >> > Hi Yakir,
> >> >> > 
> >> >> > Am Montag, 21. M?rz 2016, 20:17:46 schrieb Yakir Yang:
> >> >> >> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
> >> >> >> > Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
> >> >> >> >> This patch set would add the RGA direct rendering based 2d
> >> >> >> >> graphics
> >> >> >> >> acceleration module.
> >> >> >> > 
> >> >> >> > very cool to see that.
> >> >> >> 
> >> >> >> ;)
> >> >> >> 
> >> >> >> >> This patch set is based on git repository below:
> >> >> >> >> git://people.freedesktop.org/~airlied/linux drm-next
> >> >> >> >> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> >> >> >> >> 
> >> >> >> >> And the RGA driver is based on Exynos G2D driver, it only
> >> >> >> >> manages
> >> >> >> >> the
> >> >> >> >> command lists received from user, so user should make the
> >> >> >> >> command
> >> >> >> >> list
> >> >> >> >> to data and registers needed by operation to use.
> >> >> >> >> 
> >> >> >> >> I have prepared an userspace demo application for testing:
> >> >> >> >>    https://github.com/yakir-Yang/libdrm-rockchip
> >> >> >> >> 
> >> >> >> >> That is a rockchip libdrm library, and I have write a simple
> >> >> >> >> test
> >> >> >> >> case
> >> >> >> >> "rockchip_rga_test" that would test the below RGA features:
> >> >> >> >> - solid
> >> >> >> >> - copy
> >> >> >> >> - rotation
> >> >> >> >> - flip
> >> >> >> >> - window clip
> >> >> >> >> - dithering
> >> >> >> > 
> >> >> >> > Did you submit your libdrm changes as well?
> >> >> >> > 
> >> >> >> > Userspace-interfaces need to be stable so the other side must
> >> >> >> > also
> >> >> >> > get
> >> >> >> > accepted - even before the kernel change if I remember correctly.
> >> >> >> 
> >> >> >> Got it, and I just saw exynos_fimg2d already landed at mainline
> >> >> >> libdrm.
> >> >> >> But I don't find the way to submit patches to libdrm, would you
> >> >> >> like
> >> >> >> share some helps here ;)
> >> >> > 
> >> >> > Looking at the libdrm sources on cgit.freedesktop.org, I did not
> >> >> > find
> >> >> > any
> >> >> > specific manual on submitting patches.
> >> >> > 
> >> >> > But looking at the dri-list archive, dri-devel at lists.freedesktop.org
> >> >> > is
> >> >> > the
> >> >> > right list and looking at the libdrm history it looks like Emil
> >> >> > Velikov
> >> >> > <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in
> >> >> > libdrm.
> >> >> > And as a 3rd recipient, please also include the linux-rockchip list.
> >> >> > 
> >> >> > @Emil, please shout if I read that wrong :-)
> >> >> 
> >> >> You got it spot on Heiko. There are a few notes though...
> >> >> 
> >> >> As one reuses the existing hardware/IP block, it would be better to
> >> >> avoid copy/pasting code around.
> >> >> 
> >> >> Namely:
> >> >>  - (if possible) factor out the exynos g2d kernel functionality to a
> >> >> 
> >> >> separate kernel module and wire up the rockhip (via dt ?) to use it
> >> >> 
> >> >>  - factor out the g2d specifics out of exynos_drm.h (into
> >> >> 
> >> >> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
> >> >> new header
> >> > 
> >> > I think the IP blocks themself are quite different between Rockchip's
> >> > RGA
> >> > and Samsung's g2d and I guess the similarities are more along the lines
> >> > on how that gets integrated into the respective drm driver and
> >> > userspace.
> >> 
> >> In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
> >> obviously biased, it's better to check how others feel on the topic.
> >> 
> >> >>  - if neither of these are possible, then please ensure that the new
> >> >> 
> >> >> header uses correct types (see the docs [1]), use MIT/X11 license (if
> >> >> possible) and link where upstream userspace is happy with the
> >> >> interface (ideally more than a simple test app like libdrm)
> >> >> These might sound like an overkill, although getting UAPI right and
> >> >> maintaining it forever forces us to do so.
> >> > 
> >> > As for a real-world usecase, maybe the armsoc xserver might be somewhat
> >> > easy to use. While the core changes I did are in the core project
> >> > already, I'm still keeping the actual Rockchip support separate [0] due
> >> > to the not-yet- resolved create_gem ioctl.
> >> > 
> >> > Anyway, the armsoc xserver has some exa implementation hooks were I
> >> > guess
> >> > it might be relatively easy to hook up soc-specific things.
> >> 
> >> Ouch the armsoc ddx... Last time I've checked it felt like a place
> >> where everyone is doing his own thing, with no actual reviews and/or
> >> maintainer.
> > 
> > The development rate is pretty low and maintainership is unclear but the
> > per- soc voodoo is quite limited to the GEM-creation and everything else
> > seems somewhat nice when compared for example to the older versions of
> > the ddx.> 
> >> Iirc most/all of it's functionality was achievable with
> >> modesetting ddx (with or without glamor) ? I take it that things have
> >> changed and/or I misunderstood something ?
> > 
> > I don't really understand that whole stack or how xservers work on a whole
> > ;-) I was merely able to make the _binary_ mali-driver work with this one
> > and remembered that there were hooks for future per-soc exa functions.
> > 
> > I guess for that glamor thing you'd need an actual gpu driver and not that
> > libGL-override voodoo those crazy binary drivers do.
> > 
> > At least the modesetting ddx didn't like mali-binary-driver.
> 
> A quick rundown of the whole thing (simplified and maybe slightly off)
> - the modesetting DDX (merged in xserver for a few releases now),
> relies on GBM for buffer management and GL{,ES} for acceleration. On
> the KMS side it's as generic as any other driver should be.
> 
> I'm not sure how well modesetting works without gbm, but it should be
> able to build at least. About getting it (or others) to work with
> binary blobs... I guess you know what my and others' view is. Place
> the fact that one tries to upstream a kernel interface which,
> indirectly, interacts with such a module makes things even more ...
> lovely.
> 
> Sorry to be the bearer of bad news. If you have other ideas or others
> feels like I'm overly dramatic let me know, please.

I have the feeling we're going quite a bit off-topic right now :-) .
The binary-driver-crazyness, hasn't really anything to do with Yakir's support 
for the RGA (which is about raster-graphics-acceleration, so 2d stuff).

And me mentioning the armsoc-ddx was merely a means to allow some sort of 
different userspace user, as requested in your original mail ;-) .

Maybe you know a better use-case on where to demonstrate the viability of the 
userspace API for it as originally requested.

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-28 21:35             ` Emil Velikov
  (?)
@ 2016-03-29 11:17               ` Yakir Yang
  -1 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-29 11:17 UTC (permalink / raw)
  To: Emil Velikov, Heiko Stübner
  Cc: David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala, Ian Campbell,
	Rob Herring, Pawel Moll, Russell King, devicetree,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	LAKML

Hi Emil & Heiko,


On 03/29/2016 05:35 AM, Emil Velikov wrote:
> On 28 March 2016 at 19:44, Heiko Stübner <heiko@sntech.de> wrote:
>> Am Montag, 28. März 2016, 13:21:02 schrieb Emil Velikov:
>>> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
>>>> Hi Yakir,
>>>>
>>>> Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>>>>> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>>>>>> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>>>>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>>>>> acceleration module.
>>>>>> very cool to see that.
>>>>> ;)
>>>>>
>>>>>>> This patch set is based on git repository below:
>>>>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>>>>
>>>>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>>>>> command lists received from user, so user should make the command list
>>>>>>> to data and registers needed by operation to use.
>>>>>>>
>>>>>>> I have prepared an userspace demo application for testing:
>>>>>>>     https://github.com/yakir-Yang/libdrm-rockchip
>>>>>>>
>>>>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>>>>> "rockchip_rga_test" that would test the below RGA features:
>>>>>>> - solid
>>>>>>> - copy
>>>>>>> - rotation
>>>>>>> - flip
>>>>>>> - window clip
>>>>>>> - dithering
>>>>>> Did you submit your libdrm changes as well?
>>>>>>
>>>>>> Userspace-interfaces need to be stable so the other side must also get
>>>>>> accepted - even before the kernel change if I remember correctly.
>>>>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>>>>> But I don't find the way to submit patches to libdrm, would you like
>>>>> share some helps here ;)
>>>> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
>>>> specific manual on submitting patches.
>>>>
>>>> But looking at the dri-list archive, dri-devel@lists.freedesktop.org is
>>>> the
>>>> right list and looking at the libdrm history it looks like Emil Velikov
>>>> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
>>>> And as a 3rd recipient, please also include the linux-rockchip list.
>>>>
>>>> @Emil, please shout if I read that wrong :-)
>>> You got it spot on Heiko. There are a few notes though...
>>>
>>> As one reuses the existing hardware/IP block, it would be better to
>>> avoid copy/pasting code around.
>>> Namely:
>>>   - (if possible) factor out the exynos g2d kernel functionality to a
>>> separate kernel module and wire up the rockhip (via dt ?) to use it
>>>   - factor out the g2d specifics out of exynos_drm.h (into
>>> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
>>> new header
>> I think the IP blocks themself are quite different between Rockchip's RGA and
>> Samsung's g2d and I guess the similarities are more along the lines on how
>> that gets integrated into the respective drm driver and userspace.
>>

Yes, the hardware IP blocks is quite different. I just reference two things
from Exynos g2d code:
1. UAPI side: let userspace pass the detail mode tranform register setting
     to kernel directly, so we don't need to pass the rendering 
parameters to
     kernel, just simplify the ioctl parameters.

2. Kernel side: reference the cmdlist manager method. Two simply task: one
     for collecting the userspace register setting, another start 
rendering process.

> In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
> obviously biased, it's better to check how others feel on the topic.

Do you mean that just create an exynos_g2d_drm.h, so both exynos_drm.h
and rockchip_drm.h could include them ? It's good to reuse code, but in this
case I thought it's better to keep both exist.

I have try to do that, split the common 'exynos_g2d_drm.h'. But I 
thought it may
caused some name confusion. For example, the drm rockchip code need call the
EXYNOS_G2D_SET_CMDLIST ioctl to send command list. This may like drm 
rockchip
is calling the Exynos G2D hardware, but actually it just the name conflict.

Actually the head file is much simple, just contained 60 lines.

So, is it okay not to split the head file, just keep the data structure 
define both
rockchip_drm.h and exynos_drm.h

>>>   - if neither of these are possible, then please ensure that the new
>>> header uses correct types (see the docs [1]), use MIT/X11 license (if
>>> possible) and link where upstream userspace is happy with the
>>> interface (ideally more than a simple test app like libdrm)
>>> These might sound like an overkill, although getting UAPI right and
>>> maintaining it forever forces us to do so.
>> As for a real-world usecase, maybe the armsoc xserver might be somewhat easy
>> to use. While the core changes I did are in the core project already, I'm
>> still keeping the actual Rockchip support separate [0] due to the not-yet-
>> resolved create_gem ioctl.
>>
>> Anyway, the armsoc xserver has some exa implementation hooks were I guess it
>> might be relatively easy to hook up soc-specific things.
>>
> Ouch the armsoc ddx... Last time I've checked it felt like a place
> where everyone is doing his own thing, with no actual reviews and/or
> maintainer. Iirc most/all of it's functionality was achievable with
> modesetting ddx (with or without glamor) ? I take it that things have
> changed and/or I misunderstood something ?

Yeah, previously I plan to add RGA support to Rockchip armsoc DDX, but
seems Mark start to work on modetestting, so I may need to switch to
follow him.

Anyway, for now I just use libdrm to package the RGA interfaces.

- Yakir

> Note: The above is not meant as bashing although it hell sure looks like one.
>
> Cheers
> Emil
>
>> [0] https://github.com/mmind/xf86-video-armsoc/tree/devel/rockchip
>>
>
>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-29 11:17               ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-29 11:17 UTC (permalink / raw)
  To: Emil Velikov, Heiko Stübner
  Cc: devicetree, Russell King, Pawel Moll, Ian Campbell,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	Rob Herring, Kumar Gala, LAKML

Hi Emil & Heiko,


On 03/29/2016 05:35 AM, Emil Velikov wrote:
> On 28 March 2016 at 19:44, Heiko Stübner <heiko@sntech.de> wrote:
>> Am Montag, 28. März 2016, 13:21:02 schrieb Emil Velikov:
>>> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
>>>> Hi Yakir,
>>>>
>>>> Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>>>>> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>>>>>> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>>>>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>>>>> acceleration module.
>>>>>> very cool to see that.
>>>>> ;)
>>>>>
>>>>>>> This patch set is based on git repository below:
>>>>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>>>>
>>>>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>>>>> command lists received from user, so user should make the command list
>>>>>>> to data and registers needed by operation to use.
>>>>>>>
>>>>>>> I have prepared an userspace demo application for testing:
>>>>>>>     https://github.com/yakir-Yang/libdrm-rockchip
>>>>>>>
>>>>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>>>>> "rockchip_rga_test" that would test the below RGA features:
>>>>>>> - solid
>>>>>>> - copy
>>>>>>> - rotation
>>>>>>> - flip
>>>>>>> - window clip
>>>>>>> - dithering
>>>>>> Did you submit your libdrm changes as well?
>>>>>>
>>>>>> Userspace-interfaces need to be stable so the other side must also get
>>>>>> accepted - even before the kernel change if I remember correctly.
>>>>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>>>>> But I don't find the way to submit patches to libdrm, would you like
>>>>> share some helps here ;)
>>>> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
>>>> specific manual on submitting patches.
>>>>
>>>> But looking at the dri-list archive, dri-devel@lists.freedesktop.org is
>>>> the
>>>> right list and looking at the libdrm history it looks like Emil Velikov
>>>> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
>>>> And as a 3rd recipient, please also include the linux-rockchip list.
>>>>
>>>> @Emil, please shout if I read that wrong :-)
>>> You got it spot on Heiko. There are a few notes though...
>>>
>>> As one reuses the existing hardware/IP block, it would be better to
>>> avoid copy/pasting code around.
>>> Namely:
>>>   - (if possible) factor out the exynos g2d kernel functionality to a
>>> separate kernel module and wire up the rockhip (via dt ?) to use it
>>>   - factor out the g2d specifics out of exynos_drm.h (into
>>> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
>>> new header
>> I think the IP blocks themself are quite different between Rockchip's RGA and
>> Samsung's g2d and I guess the similarities are more along the lines on how
>> that gets integrated into the respective drm driver and userspace.
>>

Yes, the hardware IP blocks is quite different. I just reference two things
from Exynos g2d code:
1. UAPI side: let userspace pass the detail mode tranform register setting
     to kernel directly, so we don't need to pass the rendering 
parameters to
     kernel, just simplify the ioctl parameters.

2. Kernel side: reference the cmdlist manager method. Two simply task: one
     for collecting the userspace register setting, another start 
rendering process.

> In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
> obviously biased, it's better to check how others feel on the topic.

Do you mean that just create an exynos_g2d_drm.h, so both exynos_drm.h
and rockchip_drm.h could include them ? It's good to reuse code, but in this
case I thought it's better to keep both exist.

I have try to do that, split the common 'exynos_g2d_drm.h'. But I 
thought it may
caused some name confusion. For example, the drm rockchip code need call the
EXYNOS_G2D_SET_CMDLIST ioctl to send command list. This may like drm 
rockchip
is calling the Exynos G2D hardware, but actually it just the name conflict.

Actually the head file is much simple, just contained 60 lines.

So, is it okay not to split the head file, just keep the data structure 
define both
rockchip_drm.h and exynos_drm.h

>>>   - if neither of these are possible, then please ensure that the new
>>> header uses correct types (see the docs [1]), use MIT/X11 license (if
>>> possible) and link where upstream userspace is happy with the
>>> interface (ideally more than a simple test app like libdrm)
>>> These might sound like an overkill, although getting UAPI right and
>>> maintaining it forever forces us to do so.
>> As for a real-world usecase, maybe the armsoc xserver might be somewhat easy
>> to use. While the core changes I did are in the core project already, I'm
>> still keeping the actual Rockchip support separate [0] due to the not-yet-
>> resolved create_gem ioctl.
>>
>> Anyway, the armsoc xserver has some exa implementation hooks were I guess it
>> might be relatively easy to hook up soc-specific things.
>>
> Ouch the armsoc ddx... Last time I've checked it felt like a place
> where everyone is doing his own thing, with no actual reviews and/or
> maintainer. Iirc most/all of it's functionality was achievable with
> modesetting ddx (with or without glamor) ? I take it that things have
> changed and/or I misunderstood something ?

Yeah, previously I plan to add RGA support to Rockchip armsoc DDX, but
seems Mark start to work on modetestting, so I may need to switch to
follow him.

Anyway, for now I just use libdrm to package the RGA interfaces.

- Yakir

> Note: The above is not meant as bashing although it hell sure looks like one.
>
> Cheers
> Emil
>
>> [0] https://github.com/mmind/xf86-video-armsoc/tree/devel/rockchip
>>
>
>


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-29 11:17               ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-29 11:17 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Emil & Heiko,


On 03/29/2016 05:35 AM, Emil Velikov wrote:
> On 28 March 2016 at 19:44, Heiko St?bner <heiko@sntech.de> wrote:
>> Am Montag, 28. M?rz 2016, 13:21:02 schrieb Emil Velikov:
>>> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
>>>> Hi Yakir,
>>>>
>>>> Am Montag, 21. M?rz 2016, 20:17:46 schrieb Yakir Yang:
>>>>> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
>>>>>> Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
>>>>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>>>>> acceleration module.
>>>>>> very cool to see that.
>>>>> ;)
>>>>>
>>>>>>> This patch set is based on git repository below:
>>>>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>>>>
>>>>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>>>>> command lists received from user, so user should make the command list
>>>>>>> to data and registers needed by operation to use.
>>>>>>>
>>>>>>> I have prepared an userspace demo application for testing:
>>>>>>>     https://github.com/yakir-Yang/libdrm-rockchip
>>>>>>>
>>>>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>>>>> "rockchip_rga_test" that would test the below RGA features:
>>>>>>> - solid
>>>>>>> - copy
>>>>>>> - rotation
>>>>>>> - flip
>>>>>>> - window clip
>>>>>>> - dithering
>>>>>> Did you submit your libdrm changes as well?
>>>>>>
>>>>>> Userspace-interfaces need to be stable so the other side must also get
>>>>>> accepted - even before the kernel change if I remember correctly.
>>>>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>>>>> But I don't find the way to submit patches to libdrm, would you like
>>>>> share some helps here ;)
>>>> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
>>>> specific manual on submitting patches.
>>>>
>>>> But looking at the dri-list archive, dri-devel at lists.freedesktop.org is
>>>> the
>>>> right list and looking at the libdrm history it looks like Emil Velikov
>>>> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
>>>> And as a 3rd recipient, please also include the linux-rockchip list.
>>>>
>>>> @Emil, please shout if I read that wrong :-)
>>> You got it spot on Heiko. There are a few notes though...
>>>
>>> As one reuses the existing hardware/IP block, it would be better to
>>> avoid copy/pasting code around.
>>> Namely:
>>>   - (if possible) factor out the exynos g2d kernel functionality to a
>>> separate kernel module and wire up the rockhip (via dt ?) to use it
>>>   - factor out the g2d specifics out of exynos_drm.h (into
>>> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
>>> new header
>> I think the IP blocks themself are quite different between Rockchip's RGA and
>> Samsung's g2d and I guess the similarities are more along the lines on how
>> that gets integrated into the respective drm driver and userspace.
>>

Yes, the hardware IP blocks is quite different. I just reference two things
from Exynos g2d code:
1. UAPI side: let userspace pass the detail mode tranform register setting
     to kernel directly, so we don't need to pass the rendering 
parameters to
     kernel, just simplify the ioctl parameters.

2. Kernel side: reference the cmdlist manager method. Two simply task: one
     for collecting the userspace register setting, another start 
rendering process.

> In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
> obviously biased, it's better to check how others feel on the topic.

Do you mean that just create an exynos_g2d_drm.h, so both exynos_drm.h
and rockchip_drm.h could include them ? It's good to reuse code, but in this
case I thought it's better to keep both exist.

I have try to do that, split the common 'exynos_g2d_drm.h'. But I 
thought it may
caused some name confusion. For example, the drm rockchip code need call the
EXYNOS_G2D_SET_CMDLIST ioctl to send command list. This may like drm 
rockchip
is calling the Exynos G2D hardware, but actually it just the name conflict.

Actually the head file is much simple, just contained 60 lines.

So, is it okay not to split the head file, just keep the data structure 
define both
rockchip_drm.h and exynos_drm.h

>>>   - if neither of these are possible, then please ensure that the new
>>> header uses correct types (see the docs [1]), use MIT/X11 license (if
>>> possible) and link where upstream userspace is happy with the
>>> interface (ideally more than a simple test app like libdrm)
>>> These might sound like an overkill, although getting UAPI right and
>>> maintaining it forever forces us to do so.
>> As for a real-world usecase, maybe the armsoc xserver might be somewhat easy
>> to use. While the core changes I did are in the core project already, I'm
>> still keeping the actual Rockchip support separate [0] due to the not-yet-
>> resolved create_gem ioctl.
>>
>> Anyway, the armsoc xserver has some exa implementation hooks were I guess it
>> might be relatively easy to hook up soc-specific things.
>>
> Ouch the armsoc ddx... Last time I've checked it felt like a place
> where everyone is doing his own thing, with no actual reviews and/or
> maintainer. Iirc most/all of it's functionality was achievable with
> modesetting ddx (with or without glamor) ? I take it that things have
> changed and/or I misunderstood something ?

Yeah, previously I plan to add RGA support to Rockchip armsoc DDX, but
seems Mark start to work on modetestting, so I may need to switch to
follow him.

Anyway, for now I just use libdrm to package the RGA interfaces.

- Yakir

> Note: The above is not meant as bashing although it hell sure looks like one.
>
> Cheers
> Emil
>
>> [0] https://github.com/mmind/xf86-video-armsoc/tree/devel/rockchip
>>
>
>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-28 12:21         ` Emil Velikov
  (?)
@ 2016-03-29 11:40           ` Yakir Yang
  -1 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-29 11:40 UTC (permalink / raw)
  To: Emil Velikov, Heiko Stuebner
  Cc: David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala, Ian Campbell,
	Rob Herring, Pawel Moll, Russell King, devicetree,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	LAKML

Hi Emil,

On 03/28/2016 08:21 PM, Emil Velikov wrote:
> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
>> Hi Yakir,
>>
>> Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>>> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>>>> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>>> acceleration module.
>>>> very cool to see that.
>>> ;)
>>>
>>>>> This patch set is based on git repository below:
>>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>>
>>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>>> command lists received from user, so user should make the command list
>>>>> to data and registers needed by operation to use.
>>>>>
>>>>> I have prepared an userspace demo application for testing:
>>>>>     https://github.com/yakir-Yang/libdrm-rockchip
>>>>>
>>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>>> "rockchip_rga_test" that would test the below RGA features:
>>>>> - solid
>>>>> - copy
>>>>> - rotation
>>>>> - flip
>>>>> - window clip
>>>>> - dithering
>>>> Did you submit your libdrm changes as well?
>>>>
>>>> Userspace-interfaces need to be stable so the other side must also get
>>>> accepted - even before the kernel change if I remember correctly.
>>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>>> But I don't find the way to submit patches to libdrm, would you like
>>> share some helps here ;)
>> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
>> specific manual on submitting patches.
>>
>> But looking at the dri-list archive, dri-devel@lists.freedesktop.org is the
>> right list and looking at the libdrm history it looks like Emil Velikov
>> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
>> And as a 3rd recipient, please also include the linux-rockchip list.
>>
>> @Emil, please shout if I read that wrong :-)
>>
> You got it spot on Heiko. There are a few notes though...
>
> As one reuses the existing hardware/IP block, it would be better to
> avoid copy/pasting code around.
> Namely:
>   - (if possible) factor out the exynos g2d kernel functionality to a
> separate kernel module and wire up the rockhip (via dt ?) to use it
>   - factor out the g2d specifics out of exynos_drm.h (into
> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
> new header
>   - if neither of these are possible, then please ensure that the new
> header uses correct types (see the docs [1]), use MIT/X11 license (if
> possible) and link where upstream userspace is happy with the
> interface (ideally more than a simple test app like libdrm)

Whops... you have provided the third choice, nice  :-D

And I got little idea about license, where should I use the MIT/X11
license, should I declare the MIT/X11 license in kernel uapi head
file, but Andreas just remind that kernel do not allow to no GUN
license. Or may be I can:
1. Use GUN license in kernel rockchip_drm.h uapi head file
2. Use MIT/X11 license in libdrm rockchip_drm.h head file.

And I don't understand the "link where upstream userspace is happy
with the interface", could you reference small example here.

Thanks,
- Yakir

> These might sound like an overkill, although getting UAPI right and
> maintaining it forever forces us to do so.
>
> Regards,
> Emil
>
> [1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/ioctl/botching-up-ioctls.txt
>
>
>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-29 11:40           ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-29 11:40 UTC (permalink / raw)
  To: Emil Velikov, Heiko Stuebner
  Cc: devicetree, Russell King, Pawel Moll, Ian Campbell,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	Rob Herring, Kumar Gala, LAKML

Hi Emil,

On 03/28/2016 08:21 PM, Emil Velikov wrote:
> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
>> Hi Yakir,
>>
>> Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>>> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>>>> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>>> acceleration module.
>>>> very cool to see that.
>>> ;)
>>>
>>>>> This patch set is based on git repository below:
>>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>>
>>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>>> command lists received from user, so user should make the command list
>>>>> to data and registers needed by operation to use.
>>>>>
>>>>> I have prepared an userspace demo application for testing:
>>>>>     https://github.com/yakir-Yang/libdrm-rockchip
>>>>>
>>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>>> "rockchip_rga_test" that would test the below RGA features:
>>>>> - solid
>>>>> - copy
>>>>> - rotation
>>>>> - flip
>>>>> - window clip
>>>>> - dithering
>>>> Did you submit your libdrm changes as well?
>>>>
>>>> Userspace-interfaces need to be stable so the other side must also get
>>>> accepted - even before the kernel change if I remember correctly.
>>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>>> But I don't find the way to submit patches to libdrm, would you like
>>> share some helps here ;)
>> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
>> specific manual on submitting patches.
>>
>> But looking at the dri-list archive, dri-devel@lists.freedesktop.org is the
>> right list and looking at the libdrm history it looks like Emil Velikov
>> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
>> And as a 3rd recipient, please also include the linux-rockchip list.
>>
>> @Emil, please shout if I read that wrong :-)
>>
> You got it spot on Heiko. There are a few notes though...
>
> As one reuses the existing hardware/IP block, it would be better to
> avoid copy/pasting code around.
> Namely:
>   - (if possible) factor out the exynos g2d kernel functionality to a
> separate kernel module and wire up the rockhip (via dt ?) to use it
>   - factor out the g2d specifics out of exynos_drm.h (into
> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
> new header
>   - if neither of these are possible, then please ensure that the new
> header uses correct types (see the docs [1]), use MIT/X11 license (if
> possible) and link where upstream userspace is happy with the
> interface (ideally more than a simple test app like libdrm)

Whops... you have provided the third choice, nice  :-D

And I got little idea about license, where should I use the MIT/X11
license, should I declare the MIT/X11 license in kernel uapi head
file, but Andreas just remind that kernel do not allow to no GUN
license. Or may be I can:
1. Use GUN license in kernel rockchip_drm.h uapi head file
2. Use MIT/X11 license in libdrm rockchip_drm.h head file.

And I don't understand the "link where upstream userspace is happy
with the interface", could you reference small example here.

Thanks,
- Yakir

> These might sound like an overkill, although getting UAPI right and
> maintaining it forever forces us to do so.
>
> Regards,
> Emil
>
> [1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/ioctl/botching-up-ioctls.txt
>
>
>


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-29 11:40           ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-29 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Emil,

On 03/28/2016 08:21 PM, Emil Velikov wrote:
> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
>> Hi Yakir,
>>
>> Am Montag, 21. M?rz 2016, 20:17:46 schrieb Yakir Yang:
>>> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
>>>> Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
>>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>>> acceleration module.
>>>> very cool to see that.
>>> ;)
>>>
>>>>> This patch set is based on git repository below:
>>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>>
>>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>>> command lists received from user, so user should make the command list
>>>>> to data and registers needed by operation to use.
>>>>>
>>>>> I have prepared an userspace demo application for testing:
>>>>>     https://github.com/yakir-Yang/libdrm-rockchip
>>>>>
>>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>>> "rockchip_rga_test" that would test the below RGA features:
>>>>> - solid
>>>>> - copy
>>>>> - rotation
>>>>> - flip
>>>>> - window clip
>>>>> - dithering
>>>> Did you submit your libdrm changes as well?
>>>>
>>>> Userspace-interfaces need to be stable so the other side must also get
>>>> accepted - even before the kernel change if I remember correctly.
>>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>>> But I don't find the way to submit patches to libdrm, would you like
>>> share some helps here ;)
>> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
>> specific manual on submitting patches.
>>
>> But looking at the dri-list archive, dri-devel at lists.freedesktop.org is the
>> right list and looking at the libdrm history it looks like Emil Velikov
>> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
>> And as a 3rd recipient, please also include the linux-rockchip list.
>>
>> @Emil, please shout if I read that wrong :-)
>>
> You got it spot on Heiko. There are a few notes though...
>
> As one reuses the existing hardware/IP block, it would be better to
> avoid copy/pasting code around.
> Namely:
>   - (if possible) factor out the exynos g2d kernel functionality to a
> separate kernel module and wire up the rockhip (via dt ?) to use it
>   - factor out the g2d specifics out of exynos_drm.h (into
> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
> new header
>   - if neither of these are possible, then please ensure that the new
> header uses correct types (see the docs [1]), use MIT/X11 license (if
> possible) and link where upstream userspace is happy with the
> interface (ideally more than a simple test app like libdrm)

Whops... you have provided the third choice, nice  :-D

And I got little idea about license, where should I use the MIT/X11
license, should I declare the MIT/X11 license in kernel uapi head
file, but Andreas just remind that kernel do not allow to no GUN
license. Or may be I can:
1. Use GUN license in kernel rockchip_drm.h uapi head file
2. Use MIT/X11 license in libdrm rockchip_drm.h head file.

And I don't understand the "link where upstream userspace is happy
with the interface", could you reference small example here.

Thanks,
- Yakir

> These might sound like an overkill, although getting UAPI right and
> maintaining it forever forces us to do so.
>
> Regards,
> Emil
>
> [1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/ioctl/botching-up-ioctls.txt
>
>
>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-22 10:24       ` Andreas Färber
  (?)
@ 2016-03-29 11:45         ` Yakir Yang
  -1 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-29 11:45 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Heiko Stübner, devicetree, Russell King, Joonyoung Shim,
	Pawel Moll, Ian Campbell, David Airlie, linux-kernel, dri-devel,
	linux-rockchip, Rob Herring, Kumar Gala, linux-arm-kernel,
	Mark Yao

Hi Andreas,

On 03/22/2016 06:24 PM, Andreas Färber wrote:
> Hi Yakir,
>
> Am 21.03.2016 um 13:17 schrieb Yakir Yang:
>> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>>> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>> acceleration module.
>>> very cool to see that.
>> ;)
>>>> This patch set is based on git repository below:
>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>
>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>> command lists received from user, so user should make the command list
>>>> to data and registers needed by operation to use.
>>>>
>>>> I have prepared an userspace demo application for testing:
>>>>      https://github.com/yakir-Yang/libdrm-rockchip
>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>> "rockchip_rga_test" that would test the below RGA features:
>>>> - solid
>>>> - copy
>>>> - rotation
>>>> - flip
>>>> - window clip
>>>> - dithering
>>> Did you submit your libdrm changes as well?
>>>
>>> Userspace-interfaces need to be stable so the other side must also get
>>> accepted - even before the kernel change if I remember correctly.
>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>> But I don't find the way to submit patches to libdrm, would you like
>> share some helps here ;)
> If you're using Exynos as an example, please keep in mind that the
> libdrm license is MIT/X11, not GPL as the kernel. For our Linux distro
> we had to disable some Exynos parts because they snuck some GPL code in
> there and redistributing libdrm under GPL would cause a big headache
> (review of all packages directly or indirectly linking against it).

Hmmm... I just saw exynos_drm.h still declared the GNU license,
is it convince for you to share some specific example here ;)

Thanks,
- Yakir
> Thanks,
> Andreas
>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-29 11:45         ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-29 11:45 UTC (permalink / raw)
  To: Andreas Färber
  Cc: devicetree, Russell King, Pawel Moll, Ian Campbell, linux-kernel,
	dri-devel, linux-rockchip, Rob Herring, Kumar Gala,
	linux-arm-kernel

Hi Andreas,

On 03/22/2016 06:24 PM, Andreas Färber wrote:
> Hi Yakir,
>
> Am 21.03.2016 um 13:17 schrieb Yakir Yang:
>> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>>> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>> acceleration module.
>>> very cool to see that.
>> ;)
>>>> This patch set is based on git repository below:
>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>
>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>> command lists received from user, so user should make the command list
>>>> to data and registers needed by operation to use.
>>>>
>>>> I have prepared an userspace demo application for testing:
>>>>      https://github.com/yakir-Yang/libdrm-rockchip
>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>> "rockchip_rga_test" that would test the below RGA features:
>>>> - solid
>>>> - copy
>>>> - rotation
>>>> - flip
>>>> - window clip
>>>> - dithering
>>> Did you submit your libdrm changes as well?
>>>
>>> Userspace-interfaces need to be stable so the other side must also get
>>> accepted - even before the kernel change if I remember correctly.
>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>> But I don't find the way to submit patches to libdrm, would you like
>> share some helps here ;)
> If you're using Exynos as an example, please keep in mind that the
> libdrm license is MIT/X11, not GPL as the kernel. For our Linux distro
> we had to disable some Exynos parts because they snuck some GPL code in
> there and redistributing libdrm under GPL would cause a big headache
> (review of all packages directly or indirectly linking against it).

Hmmm... I just saw exynos_drm.h still declared the GNU license,
is it convince for you to share some specific example here ;)

Thanks,
- Yakir
> Thanks,
> Andreas
>


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-29 11:45         ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-29 11:45 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Andreas,

On 03/22/2016 06:24 PM, Andreas F?rber wrote:
> Hi Yakir,
>
> Am 21.03.2016 um 13:17 schrieb Yakir Yang:
>> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
>>> Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>> acceleration module.
>>> very cool to see that.
>> ;)
>>>> This patch set is based on git repository below:
>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>
>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>> command lists received from user, so user should make the command list
>>>> to data and registers needed by operation to use.
>>>>
>>>> I have prepared an userspace demo application for testing:
>>>>      https://github.com/yakir-Yang/libdrm-rockchip
>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>> "rockchip_rga_test" that would test the below RGA features:
>>>> - solid
>>>> - copy
>>>> - rotation
>>>> - flip
>>>> - window clip
>>>> - dithering
>>> Did you submit your libdrm changes as well?
>>>
>>> Userspace-interfaces need to be stable so the other side must also get
>>> accepted - even before the kernel change if I remember correctly.
>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>> But I don't find the way to submit patches to libdrm, would you like
>> share some helps here ;)
> If you're using Exynos as an example, please keep in mind that the
> libdrm license is MIT/X11, not GPL as the kernel. For our Linux distro
> we had to disable some Exynos parts because they snuck some GPL code in
> there and redistributing libdrm under GPL would cause a big headache
> (review of all packages directly or indirectly linking against it).

Hmmm... I just saw exynos_drm.h still declared the GNU license,
is it convince for you to share some specific example here ;)

Thanks,
- Yakir
> Thanks,
> Andreas
>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-29 11:17               ` Yakir Yang
@ 2016-03-29 11:47                 ` Heiko Stübner
  -1 siblings, 0 replies; 73+ messages in thread
From: Heiko Stübner @ 2016-03-29 11:47 UTC (permalink / raw)
  To: Yakir Yang
  Cc: Emil Velikov, David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	linux-kernel, ML dri-devel, linux-rockchip, LAKML

Am Dienstag, 29. März 2016, 19:17:12 schrieb Yakir Yang:
> Hi Emil & Heiko,
> 
> On 03/29/2016 05:35 AM, Emil Velikov wrote:
> > On 28 March 2016 at 19:44, Heiko Stübner <heiko@sntech.de> wrote:
> >> Am Montag, 28. März 2016, 13:21:02 schrieb Emil Velikov:
> >>> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
> >>>> Hi Yakir,
> >>>> 
> >>>> Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
> >>>>> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
> >>>>>> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
> >>>>>>> This patch set would add the RGA direct rendering based 2d graphics
> >>>>>>> acceleration module.
> >>>>>> 
> >>>>>> very cool to see that.
> >>>>> 
> >>>>> ;)
> >>>>> 
> >>>>>>> This patch set is based on git repository below:
> >>>>>>> git://people.freedesktop.org/~airlied/linux drm-next
> >>>>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> >>>>>>> 
> >>>>>>> And the RGA driver is based on Exynos G2D driver, it only manages
> >>>>>>> the
> >>>>>>> command lists received from user, so user should make the command
> >>>>>>> list
> >>>>>>> to data and registers needed by operation to use.
> >>>>>>> 
> >>>>>>> I have prepared an userspace demo application for testing:
> >>>>>>>     https://github.com/yakir-Yang/libdrm-rockchip
> >>>>>>> 
> >>>>>>> That is a rockchip libdrm library, and I have write a simple test
> >>>>>>> case
> >>>>>>> "rockchip_rga_test" that would test the below RGA features:
> >>>>>>> - solid
> >>>>>>> - copy
> >>>>>>> - rotation
> >>>>>>> - flip
> >>>>>>> - window clip
> >>>>>>> - dithering
> >>>>>> 
> >>>>>> Did you submit your libdrm changes as well?
> >>>>>> 
> >>>>>> Userspace-interfaces need to be stable so the other side must also
> >>>>>> get
> >>>>>> accepted - even before the kernel change if I remember correctly.
> >>>>> 
> >>>>> Got it, and I just saw exynos_fimg2d already landed at mainline
> >>>>> libdrm.
> >>>>> But I don't find the way to submit patches to libdrm, would you like
> >>>>> share some helps here ;)
> >>>> 
> >>>> Looking at the libdrm sources on cgit.freedesktop.org, I did not find
> >>>> any
> >>>> specific manual on submitting patches.
> >>>> 
> >>>> But looking at the dri-list archive, dri-devel@lists.freedesktop.org is
> >>>> the
> >>>> right list and looking at the libdrm history it looks like Emil Velikov
> >>>> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in
> >>>> libdrm.
> >>>> And as a 3rd recipient, please also include the linux-rockchip list.
> >>>> 
> >>>> @Emil, please shout if I read that wrong :-)
> >>> 
> >>> You got it spot on Heiko. There are a few notes though...
> >>> 
> >>> As one reuses the existing hardware/IP block, it would be better to
> >>> avoid copy/pasting code around.
> >>> 
> >>> Namely:
> >>>   - (if possible) factor out the exynos g2d kernel functionality to a
> >>> 
> >>> separate kernel module and wire up the rockhip (via dt ?) to use it
> >>> 
> >>>   - factor out the g2d specifics out of exynos_drm.h (into
> >>> 
> >>> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
> >>> new header
> >> 
> >> I think the IP blocks themself are quite different between Rockchip's RGA
> >> and Samsung's g2d and I guess the similarities are more along the lines
> >> on how that gets integrated into the respective drm driver and
> >> userspace.
> Yes, the hardware IP blocks is quite different. I just reference two things
> from Exynos g2d code:
> 1. UAPI side: let userspace pass the detail mode tranform register setting
>      to kernel directly, so we don't need to pass the rendering
> parameters to
>      kernel, just simplify the ioctl parameters.
> 
> 2. Kernel side: reference the cmdlist manager method. Two simply task: one
>      for collecting the userspace register setting, another start
> rendering process.
> 
> > In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
> > obviously biased, it's better to check how others feel on the topic.
> 
> Do you mean that just create an exynos_g2d_drm.h, so both exynos_drm.h
> and rockchip_drm.h could include them ? It's good to reuse code, but in this
> case I thought it's better to keep both exist.
> 
> I have try to do that, split the common 'exynos_g2d_drm.h'. But I
> thought it may
> caused some name confusion. For example, the drm rockchip code need call the
> EXYNOS_G2D_SET_CMDLIST ioctl to send command list. This may like drm
> rockchip
> is calling the Exynos G2D hardware, but actually it just the name conflict.
> 
> Actually the head file is much simple, just contained 60 lines.
> 
> So, is it okay not to split the head file, just keep the data structure
> define both
> rockchip_drm.h and exynos_drm.h
> 
> >>>   - if neither of these are possible, then please ensure that the new
> >>> 
> >>> header uses correct types (see the docs [1]), use MIT/X11 license (if
> >>> possible) and link where upstream userspace is happy with the
> >>> interface (ideally more than a simple test app like libdrm)
> >>> These might sound like an overkill, although getting UAPI right and
> >>> maintaining it forever forces us to do so.
> >> 
> >> As for a real-world usecase, maybe the armsoc xserver might be somewhat
> >> easy to use. While the core changes I did are in the core project
> >> already, I'm still keeping the actual Rockchip support separate [0] due
> >> to the not-yet- resolved create_gem ioctl.
> >> 
> >> Anyway, the armsoc xserver has some exa implementation hooks were I guess
> >> it might be relatively easy to hook up soc-specific things.
> > 
> > Ouch the armsoc ddx... Last time I've checked it felt like a place
> > where everyone is doing his own thing, with no actual reviews and/or
> > maintainer. Iirc most/all of it's functionality was achievable with
> > modesetting ddx (with or without glamor) ? I take it that things have
> > changed and/or I misunderstood something ?
> 
> Yeah, previously I plan to add RGA support to Rockchip armsoc DDX, but
> seems Mark start to work on modetestting, so I may need to switch to
> follow him.

It is great to hear that people who actually know what they're doing in 
graphics-land are working on x11 support :-D .


Heiko

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-29 11:47                 ` Heiko Stübner
  0 siblings, 0 replies; 73+ messages in thread
From: Heiko Stübner @ 2016-03-29 11:47 UTC (permalink / raw)
  To: linux-arm-kernel

Am Dienstag, 29. M?rz 2016, 19:17:12 schrieb Yakir Yang:
> Hi Emil & Heiko,
> 
> On 03/29/2016 05:35 AM, Emil Velikov wrote:
> > On 28 March 2016 at 19:44, Heiko St?bner <heiko@sntech.de> wrote:
> >> Am Montag, 28. M?rz 2016, 13:21:02 schrieb Emil Velikov:
> >>> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
> >>>> Hi Yakir,
> >>>> 
> >>>> Am Montag, 21. M?rz 2016, 20:17:46 schrieb Yakir Yang:
> >>>>> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
> >>>>>> Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
> >>>>>>> This patch set would add the RGA direct rendering based 2d graphics
> >>>>>>> acceleration module.
> >>>>>> 
> >>>>>> very cool to see that.
> >>>>> 
> >>>>> ;)
> >>>>> 
> >>>>>>> This patch set is based on git repository below:
> >>>>>>> git://people.freedesktop.org/~airlied/linux drm-next
> >>>>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
> >>>>>>> 
> >>>>>>> And the RGA driver is based on Exynos G2D driver, it only manages
> >>>>>>> the
> >>>>>>> command lists received from user, so user should make the command
> >>>>>>> list
> >>>>>>> to data and registers needed by operation to use.
> >>>>>>> 
> >>>>>>> I have prepared an userspace demo application for testing:
> >>>>>>>     https://github.com/yakir-Yang/libdrm-rockchip
> >>>>>>> 
> >>>>>>> That is a rockchip libdrm library, and I have write a simple test
> >>>>>>> case
> >>>>>>> "rockchip_rga_test" that would test the below RGA features:
> >>>>>>> - solid
> >>>>>>> - copy
> >>>>>>> - rotation
> >>>>>>> - flip
> >>>>>>> - window clip
> >>>>>>> - dithering
> >>>>>> 
> >>>>>> Did you submit your libdrm changes as well?
> >>>>>> 
> >>>>>> Userspace-interfaces need to be stable so the other side must also
> >>>>>> get
> >>>>>> accepted - even before the kernel change if I remember correctly.
> >>>>> 
> >>>>> Got it, and I just saw exynos_fimg2d already landed at mainline
> >>>>> libdrm.
> >>>>> But I don't find the way to submit patches to libdrm, would you like
> >>>>> share some helps here ;)
> >>>> 
> >>>> Looking at the libdrm sources on cgit.freedesktop.org, I did not find
> >>>> any
> >>>> specific manual on submitting patches.
> >>>> 
> >>>> But looking at the dri-list archive, dri-devel at lists.freedesktop.org is
> >>>> the
> >>>> right list and looking at the libdrm history it looks like Emil Velikov
> >>>> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in
> >>>> libdrm.
> >>>> And as a 3rd recipient, please also include the linux-rockchip list.
> >>>> 
> >>>> @Emil, please shout if I read that wrong :-)
> >>> 
> >>> You got it spot on Heiko. There are a few notes though...
> >>> 
> >>> As one reuses the existing hardware/IP block, it would be better to
> >>> avoid copy/pasting code around.
> >>> 
> >>> Namely:
> >>>   - (if possible) factor out the exynos g2d kernel functionality to a
> >>> 
> >>> separate kernel module and wire up the rockhip (via dt ?) to use it
> >>> 
> >>>   - factor out the g2d specifics out of exynos_drm.h (into
> >>> 
> >>> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
> >>> new header
> >> 
> >> I think the IP blocks themself are quite different between Rockchip's RGA
> >> and Samsung's g2d and I guess the similarities are more along the lines
> >> on how that gets integrated into the respective drm driver and
> >> userspace.
> Yes, the hardware IP blocks is quite different. I just reference two things
> from Exynos g2d code:
> 1. UAPI side: let userspace pass the detail mode tranform register setting
>      to kernel directly, so we don't need to pass the rendering
> parameters to
>      kernel, just simplify the ioctl parameters.
> 
> 2. Kernel side: reference the cmdlist manager method. Two simply task: one
>      for collecting the userspace register setting, another start
> rendering process.
> 
> > In this case, the exynos_g2d_drm.h seems like a good idea. As I'm
> > obviously biased, it's better to check how others feel on the topic.
> 
> Do you mean that just create an exynos_g2d_drm.h, so both exynos_drm.h
> and rockchip_drm.h could include them ? It's good to reuse code, but in this
> case I thought it's better to keep both exist.
> 
> I have try to do that, split the common 'exynos_g2d_drm.h'. But I
> thought it may
> caused some name confusion. For example, the drm rockchip code need call the
> EXYNOS_G2D_SET_CMDLIST ioctl to send command list. This may like drm
> rockchip
> is calling the Exynos G2D hardware, but actually it just the name conflict.
> 
> Actually the head file is much simple, just contained 60 lines.
> 
> So, is it okay not to split the head file, just keep the data structure
> define both
> rockchip_drm.h and exynos_drm.h
> 
> >>>   - if neither of these are possible, then please ensure that the new
> >>> 
> >>> header uses correct types (see the docs [1]), use MIT/X11 license (if
> >>> possible) and link where upstream userspace is happy with the
> >>> interface (ideally more than a simple test app like libdrm)
> >>> These might sound like an overkill, although getting UAPI right and
> >>> maintaining it forever forces us to do so.
> >> 
> >> As for a real-world usecase, maybe the armsoc xserver might be somewhat
> >> easy to use. While the core changes I did are in the core project
> >> already, I'm still keeping the actual Rockchip support separate [0] due
> >> to the not-yet- resolved create_gem ioctl.
> >> 
> >> Anyway, the armsoc xserver has some exa implementation hooks were I guess
> >> it might be relatively easy to hook up soc-specific things.
> > 
> > Ouch the armsoc ddx... Last time I've checked it felt like a place
> > where everyone is doing his own thing, with no actual reviews and/or
> > maintainer. Iirc most/all of it's functionality was achievable with
> > modesetting ddx (with or without glamor) ? I take it that things have
> > changed and/or I misunderstood something ?
> 
> Yeah, previously I plan to add RGA support to Rockchip armsoc DDX, but
> seems Mark start to work on modetestting, so I may need to switch to
> follow him.

It is great to hear that people who actually know what they're doing in 
graphics-land are working on x11 support :-D .


Heiko

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 2/4] drm: rockchip: add RGA driver support
       [not found]   ` <20160323142021.GA19977@rob-hp-laptop>
@ 2016-03-29 11:50     ` Yakir Yang
  0 siblings, 0 replies; 73+ messages in thread
From: Yakir Yang @ 2016-03-29 11:50 UTC (permalink / raw)
  To: Rob Herring, linux-rockchip, dri-devel

Hi Rob,

+ rockchip / dri email list back

On 03/23/2016 10:20 PM, Rob Herring wrote:
> On Mon, Mar 21, 2016 at 05:40:06PM +0800, Yakir Yang wrote:
>> Rockchip RGA is a separate 2D raster graphic acceleration unit. It
>> accelerates 2D graphics operations, such as point/line drawing, image
>> scaling, rotation, BitBLT, alpha blending and image blur/sharpness.
>>
>> The RGA driver is based on Exynos G2D driver, it is performed by two
>> tasks simply.
>> 1. Configures the rendering parameters, such as foreground color and
>>     coordinates data by setting the drawing context registers.
>> 2. Start the rendering process by calling rga_exec() ioctl.
>>
>> The RGA supports DMA mode as host interface. User can make command list
>> to reduce HOST(ARM) loads. The contents of The command list is setted to
>> relevant registers of RGA by DMA.
>>
>> The command list is composed Header and command sets and Tail.
>> - Header: The number of command set(4Bytes)
>> - Command set: Register offset(4Bytes) + Register data(4Bytes)
>> - Tail: Pointer of base address of the other command list(4Bytes)
>>
>> By Tail field, the G2D can process many command lists without halt at
>> one go.
>>
>> The G2D has following the rendering pipeline.
>>                 --->     Color Fill     --->
>>                 |                          |
>> --> DMA (read) ---> Src Bitmap Process ----> Alpha/ROP ---> Format convert ---> DMA (Write)
>>                 |                          |
>>                 ---> Dst Bitmap Process --->
>>
>> And supports various operations from the rendering pipeline.
>> - copy
>> - fast solid color fill
>> - rotation
>> - flip
>> - 4 operand raster operation(ROP4)
>> - alpha blending
>> - color key
>> - dithering
>> - etc
>>
>> User should make the command list to data and registers needed by
>> operation to use. The Rockchip RGA driver only manages the command lists
>> received from user. Some registers needs memory base address(physical
>> address) of image. User doesn't know its physical address, so fills the
>> gem handle of that memory than address to command sets, then RGA driver
>> converts it to memory base address.
>>
>> We adds three ioctls for Rockchip RGA.
>>
>> - ioctls
>> DRM_ROCKCHIP_RGA_GET_VER: get the RGA hardware version
>> DRM_ROCKCHIP_RGA_SET_CMDLIST: set the command list from user to driver
>> DRM_ROCKCHIP_RGA_EXEC: execute the command lists setted to driver
>>
>> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
>> ---
>>   .../bindings/display/rockchip/rockchip-rga.txt     |  36 +
>>   drivers/gpu/drm/rockchip/Kconfig                   |   9 +
>>   drivers/gpu/drm/rockchip/Makefile                  |   1 +
>>   drivers/gpu/drm/rockchip/rockchip_drm_drv.c        |  35 +-
>>   drivers/gpu/drm/rockchip/rockchip_drm_drv.h        |   4 +
>>   drivers/gpu/drm/rockchip/rockchip_drm_rga.c        | 977 +++++++++++++++++++++
>>   drivers/gpu/drm/rockchip/rockchip_drm_rga.h        | 108 +++
>>   include/uapi/drm/rockchip_drm.h                    |  63 ++
>>   8 files changed, 1232 insertions(+), 1 deletion(-)
>>   create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
>>   create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.c
>>   create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.h
>>   create mode 100644 include/uapi/drm/rockchip_drm.h
>>
>> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
>> new file mode 100644
>> index 0000000..0c606cb
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
>> @@ -0,0 +1,36 @@
>> +device-tree bindings for rockchip 2D raster graphic acceleration controller (RGA)
> s/rockchip/RockChip/
Done
>> +
>> +RGA is a separate 2D raster graphic acceleration unit. It accelerates 2D
>> +graphics operations, such as point/line drawing, image scaling, rotation,
>> +BitBLT, alpha blending and image blur/sharpness.
>> +
>> +Required properties:
>> +- compatible: value should be one of the following
>> +		"rockchip,rk3228-rga";
>> +		"rockchip,rk3288-rga";
>> +		"rockchip,rk3399-rga";
>> +
>> +- interrupts: RGA interrupt number.
>> +
>> +- clocks: phandle to RGA sclk/hclk/aclk clocks
>> +
>> +- clock-names: should be "aclk" "hclk" and "sclk"
> comma                             ^
>
> You have different orders for clocks and clock-names. Please be clear
> what the order is.
>
Okay
>> +
>> +- resets: Must contain an entry for each entry in reset-names.
>> +  See ../reset/reset.txt for details.
>> +- reset-names: should be "aclk" "hclk" and "sclk"
> Same as clocks?
I should rename them to "core", "axi" and "ahb"
>> +
>> +Example:
>> +SoC specific DT entry:
>> +	rga: rga@ff680000 {
> gpu@... to be generic
Done
>> +		compatible = "rockchip,rk3399-rga";
>> +		reg = <0xff680000 0x10000>;
>> +		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
>> +		interrupt-names = "rga";
> Not documented. interrupt-names is pointless for single irq, so just
> drop it.
Okay
>> +		clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>;
>> +		clock-names = "aclk", "hclk", "sclk";
>> +
>> +		resets = <&cru SRST_A_RGA>, <&cru SRST_H_RGA>, <&cru SRST_RGA_CORE>;
>> +		reset-names = "aclk", "hclk", "sclk";
>> +		status = "disabled";
>> +	};
>
>


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-28 22:13                   ` Heiko Stübner
  (?)
@ 2016-03-29 13:13                     ` Emil Velikov
  -1 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-29 13:13 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Yakir Yang, David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	LAKML

On 28 March 2016 at 23:13, Heiko Stübner <heiko@sntech.de> wrote:

> I have the feeling we're going quite a bit off-topic right now :-) .
> The binary-driver-crazyness, hasn't really anything to do with Yakir's support
> for the RGA (which is about raster-graphics-acceleration, so 2d stuff).
>
> And me mentioning the armsoc-ddx was merely a means to allow some sort of
> different userspace user, as requested in your original mail ;-) .
>
Seems like I forgot to state the obvious - for all the reasons
mentioned, the armsoc ddx seems like a bad example.

> Maybe you know a better use-case on where to demonstrate the viability of the
> userspace API for it as originally requested.
I'm afraid that my RockChip-foo is extremely limited. Perhaps the
actual user of these should be mentioned ? xf86-video-rockhip (is
there one ?) or any other effort/project that lacks some (all?) of the
criticism listed.

(Sort of) the bottom line - either reuse the existing interfaces or
provide an approved, full blown userspace (libdrm demos/programs do
not count) that uses the new interfaces.

I haven't made these rules, just a fool^Wguy that repeats them so that
people don't abuse them much. If in doubt check with Dave and Daniel V
- they had enough repeating these.

-Emil

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-29 13:13                     ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-29 13:13 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Yakir Yang, David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	LAKML

On 28 March 2016 at 23:13, Heiko Stübner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org> wrote:

> I have the feeling we're going quite a bit off-topic right now :-) .
> The binary-driver-crazyness, hasn't really anything to do with Yakir's support
> for the RGA (which is about raster-graphics-acceleration, so 2d stuff).
>
> And me mentioning the armsoc-ddx was merely a means to allow some sort of
> different userspace user, as requested in your original mail ;-) .
>
Seems like I forgot to state the obvious - for all the reasons
mentioned, the armsoc ddx seems like a bad example.

> Maybe you know a better use-case on where to demonstrate the viability of the
> userspace API for it as originally requested.
I'm afraid that my RockChip-foo is extremely limited. Perhaps the
actual user of these should be mentioned ? xf86-video-rockhip (is
there one ?) or any other effort/project that lacks some (all?) of the
criticism listed.

(Sort of) the bottom line - either reuse the existing interfaces or
provide an approved, full blown userspace (libdrm demos/programs do
not count) that uses the new interfaces.

I haven't made these rules, just a fool^Wguy that repeats them so that
people don't abuse them much. If in doubt check with Dave and Daniel V
- they had enough repeating these.

-Emil
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-29 13:13                     ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-29 13:13 UTC (permalink / raw)
  To: linux-arm-kernel

On 28 March 2016 at 23:13, Heiko St?bner <heiko@sntech.de> wrote:

> I have the feeling we're going quite a bit off-topic right now :-) .
> The binary-driver-crazyness, hasn't really anything to do with Yakir's support
> for the RGA (which is about raster-graphics-acceleration, so 2d stuff).
>
> And me mentioning the armsoc-ddx was merely a means to allow some sort of
> different userspace user, as requested in your original mail ;-) .
>
Seems like I forgot to state the obvious - for all the reasons
mentioned, the armsoc ddx seems like a bad example.

> Maybe you know a better use-case on where to demonstrate the viability of the
> userspace API for it as originally requested.
I'm afraid that my RockChip-foo is extremely limited. Perhaps the
actual user of these should be mentioned ? xf86-video-rockhip (is
there one ?) or any other effort/project that lacks some (all?) of the
criticism listed.

(Sort of) the bottom line - either reuse the existing interfaces or
provide an approved, full blown userspace (libdrm demos/programs do
not count) that uses the new interfaces.

I haven't made these rules, just a fool^Wguy that repeats them so that
people don't abuse them much. If in doubt check with Dave and Daniel V
- they had enough repeating these.

-Emil

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-29 13:27             ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-29 13:27 UTC (permalink / raw)
  To: Yakir Yang
  Cc: Heiko Stuebner, David Airlie, Mark Yao, Joonyoung Shim,
	Kumar Gala, Ian Campbell, Rob Herring, Pawel Moll, Russell King,
	devicetree, Linux-Kernel@Vger. Kernel. Org, ML dri-devel,
	linux-rockchip, LAKML

Hi Yakir,

On 29 March 2016 at 12:40, Yakir Yang <ykk@rock-chips.com> wrote:
> Hi Emil,
>
> On 03/28/2016 08:21 PM, Emil Velikov wrote:
>>
>> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
>>>
>>> Hi Yakir,
>>>
>>> Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>>>>
>>>> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>>>>>
>>>>> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>>>>>>
>>>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>>>> acceleration module.
>>>>>
>>>>> very cool to see that.
>>>>
>>>> ;)
>>>>
>>>>>> This patch set is based on git repository below:
>>>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>>>
>>>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>>>> command lists received from user, so user should make the command list
>>>>>> to data and registers needed by operation to use.
>>>>>>
>>>>>> I have prepared an userspace demo application for testing:
>>>>>>     https://github.com/yakir-Yang/libdrm-rockchip
>>>>>>
>>>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>>>> "rockchip_rga_test" that would test the below RGA features:
>>>>>> - solid
>>>>>> - copy
>>>>>> - rotation
>>>>>> - flip
>>>>>> - window clip
>>>>>> - dithering
>>>>>
>>>>> Did you submit your libdrm changes as well?
>>>>>
>>>>> Userspace-interfaces need to be stable so the other side must also get
>>>>> accepted - even before the kernel change if I remember correctly.
>>>>
>>>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>>>> But I don't find the way to submit patches to libdrm, would you like
>>>> share some helps here ;)
>>>
>>> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
>>> specific manual on submitting patches.
>>>
>>> But looking at the dri-list archive, dri-devel@lists.freedesktop.org is
>>> the
>>> right list and looking at the libdrm history it looks like Emil Velikov
>>> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
>>> And as a 3rd recipient, please also include the linux-rockchip list.
>>>
>>> @Emil, please shout if I read that wrong :-)
>>>
>> You got it spot on Heiko. There are a few notes though...
>>
>> As one reuses the existing hardware/IP block, it would be better to
>> avoid copy/pasting code around.
>> Namely:
>>   - (if possible) factor out the exynos g2d kernel functionality to a
>> separate kernel module and wire up the rockhip (via dt ?) to use it
>>   - factor out the g2d specifics out of exynos_drm.h (into
>> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
>> new header
>>   - if neither of these are possible, then please ensure that the new
>> header uses correct types (see the docs [1]), use MIT/X11 license (if
>> possible) and link where upstream userspace is happy with the
>> interface (ideally more than a simple test app like libdrm)
>
>
> Whops... you have provided the third choice, nice  :-D
>
> And I got little idea about license, where should I use the MIT/X11
> license, should I declare the MIT/X11 license in kernel uapi head
> file, but Andreas just remind that kernel do not allow to no GUN
> license. Or may be I can:
Now that's a lovely typo - (GNU vs GUN) :-)

But seriously - what makes you think that the kernel does not allow
MIT/X11 licensed code ? Most of the DRM subsystem uses it.

> 1. Use GUN license in kernel rockchip_drm.h uapi head file
> 2. Use MIT/X11 license in libdrm rockchip_drm.h head file.
>
I would suggest keeping the license the same in both places (the
libdrm ones should be a direct copy of the kernel one produced with
`make headers_install`), regardless of which one you opt for.

> And I don't understand the "link where upstream userspace is happy
> with the interface", could you reference small example here.
>
Already mentioned elsewhere but for posterity:

If designing a new interface one should provide a reference to a
maintained upstream project, where the design was approved. Reason
being is that unlike ChromeOS's kernel upstream one gets to keep its
interfaces forever. And yes, I realise that CrOS folks are trying
really hard to upstream things and use vanilla kernel.

Regards,
Emil

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-29 13:27             ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-29 13:27 UTC (permalink / raw)
  To: Yakir Yang
  Cc: Heiko Stuebner, David Airlie, Mark Yao, Joonyoung Shim,
	Kumar Gala, Ian Campbell, Rob Herring, Pawel Moll, Russell King,
	devicetree, Linux-Kernel@Vger. Kernel. Org, ML dri-devel,
	linux-rockchip, LAKML

Hi Yakir,

On 29 March 2016 at 12:40, Yakir Yang <ykk-TNX95d0MmH7DzftRWevZcw@public.gmane.org> wrote:
> Hi Emil,
>
> On 03/28/2016 08:21 PM, Emil Velikov wrote:
>>
>> On 22 March 2016 at 00:42, Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org> wrote:
>>>
>>> Hi Yakir,
>>>
>>> Am Montag, 21. März 2016, 20:17:46 schrieb Yakir Yang:
>>>>
>>>> On 03/21/2016 07:29 PM, Heiko Stübner wrote:
>>>>>
>>>>> Am Montag, 21. März 2016, 17:28:38 schrieb Yakir Yang:
>>>>>>
>>>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>>>> acceleration module.
>>>>>
>>>>> very cool to see that.
>>>>
>>>> ;)
>>>>
>>>>>> This patch set is based on git repository below:
>>>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>>>
>>>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>>>> command lists received from user, so user should make the command list
>>>>>> to data and registers needed by operation to use.
>>>>>>
>>>>>> I have prepared an userspace demo application for testing:
>>>>>>     https://github.com/yakir-Yang/libdrm-rockchip
>>>>>>
>>>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>>>> "rockchip_rga_test" that would test the below RGA features:
>>>>>> - solid
>>>>>> - copy
>>>>>> - rotation
>>>>>> - flip
>>>>>> - window clip
>>>>>> - dithering
>>>>>
>>>>> Did you submit your libdrm changes as well?
>>>>>
>>>>> Userspace-interfaces need to be stable so the other side must also get
>>>>> accepted - even before the kernel change if I remember correctly.
>>>>
>>>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>>>> But I don't find the way to submit patches to libdrm, would you like
>>>> share some helps here ;)
>>>
>>> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
>>> specific manual on submitting patches.
>>>
>>> But looking at the dri-list archive, dri-devel-PD4FTy7X32lNgt0PjOBp9/EVdHwE84te@public.gmane.orgg is
>>> the
>>> right list and looking at the libdrm history it looks like Emil Velikov
>>> <emil.l.velikov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> seems to be doing maintenance-stuff in libdrm.
>>> And as a 3rd recipient, please also include the linux-rockchip list.
>>>
>>> @Emil, please shout if I read that wrong :-)
>>>
>> You got it spot on Heiko. There are a few notes though...
>>
>> As one reuses the existing hardware/IP block, it would be better to
>> avoid copy/pasting code around.
>> Namely:
>>   - (if possible) factor out the exynos g2d kernel functionality to a
>> separate kernel module and wire up the rockhip (via dt ?) to use it
>>   - factor out the g2d specifics out of exynos_drm.h (into
>> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
>> new header
>>   - if neither of these are possible, then please ensure that the new
>> header uses correct types (see the docs [1]), use MIT/X11 license (if
>> possible) and link where upstream userspace is happy with the
>> interface (ideally more than a simple test app like libdrm)
>
>
> Whops... you have provided the third choice, nice  :-D
>
> And I got little idea about license, where should I use the MIT/X11
> license, should I declare the MIT/X11 license in kernel uapi head
> file, but Andreas just remind that kernel do not allow to no GUN
> license. Or may be I can:
Now that's a lovely typo - (GNU vs GUN) :-)

But seriously - what makes you think that the kernel does not allow
MIT/X11 licensed code ? Most of the DRM subsystem uses it.

> 1. Use GUN license in kernel rockchip_drm.h uapi head file
> 2. Use MIT/X11 license in libdrm rockchip_drm.h head file.
>
I would suggest keeping the license the same in both places (the
libdrm ones should be a direct copy of the kernel one produced with
`make headers_install`), regardless of which one you opt for.

> And I don't understand the "link where upstream userspace is happy
> with the interface", could you reference small example here.
>
Already mentioned elsewhere but for posterity:

If designing a new interface one should provide a reference to a
maintained upstream project, where the design was approved. Reason
being is that unlike ChromeOS's kernel upstream one gets to keep its
interfaces forever. And yes, I realise that CrOS folks are trying
really hard to upstream things and use vanilla kernel.

Regards,
Emil
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-29 13:27             ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-29 13:27 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Yakir,

On 29 March 2016 at 12:40, Yakir Yang <ykk@rock-chips.com> wrote:
> Hi Emil,
>
> On 03/28/2016 08:21 PM, Emil Velikov wrote:
>>
>> On 22 March 2016 at 00:42, Heiko Stuebner <heiko@sntech.de> wrote:
>>>
>>> Hi Yakir,
>>>
>>> Am Montag, 21. M?rz 2016, 20:17:46 schrieb Yakir Yang:
>>>>
>>>> On 03/21/2016 07:29 PM, Heiko St?bner wrote:
>>>>>
>>>>> Am Montag, 21. M?rz 2016, 17:28:38 schrieb Yakir Yang:
>>>>>>
>>>>>> This patch set would add the RGA direct rendering based 2d graphics
>>>>>> acceleration module.
>>>>>
>>>>> very cool to see that.
>>>>
>>>> ;)
>>>>
>>>>>> This patch set is based on git repository below:
>>>>>> git://people.freedesktop.org/~airlied/linux drm-next
>>>>>> commit id: 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7
>>>>>>
>>>>>> And the RGA driver is based on Exynos G2D driver, it only manages the
>>>>>> command lists received from user, so user should make the command list
>>>>>> to data and registers needed by operation to use.
>>>>>>
>>>>>> I have prepared an userspace demo application for testing:
>>>>>>     https://github.com/yakir-Yang/libdrm-rockchip
>>>>>>
>>>>>> That is a rockchip libdrm library, and I have write a simple test case
>>>>>> "rockchip_rga_test" that would test the below RGA features:
>>>>>> - solid
>>>>>> - copy
>>>>>> - rotation
>>>>>> - flip
>>>>>> - window clip
>>>>>> - dithering
>>>>>
>>>>> Did you submit your libdrm changes as well?
>>>>>
>>>>> Userspace-interfaces need to be stable so the other side must also get
>>>>> accepted - even before the kernel change if I remember correctly.
>>>>
>>>> Got it, and I just saw exynos_fimg2d already landed at mainline libdrm.
>>>> But I don't find the way to submit patches to libdrm, would you like
>>>> share some helps here ;)
>>>
>>> Looking at the libdrm sources on cgit.freedesktop.org, I did not find any
>>> specific manual on submitting patches.
>>>
>>> But looking at the dri-list archive, dri-devel at lists.freedesktop.org is
>>> the
>>> right list and looking at the libdrm history it looks like Emil Velikov
>>> <emil.l.velikov@gmail.com> seems to be doing maintenance-stuff in libdrm.
>>> And as a 3rd recipient, please also include the linux-rockchip list.
>>>
>>> @Emil, please shout if I read that wrong :-)
>>>
>> You got it spot on Heiko. There are a few notes though...
>>
>> As one reuses the existing hardware/IP block, it would be better to
>> avoid copy/pasting code around.
>> Namely:
>>   - (if possible) factor out the exynos g2d kernel functionality to a
>> separate kernel module and wire up the rockhip (via dt ?) to use it
>>   - factor out the g2d specifics out of exynos_drm.h (into
>> exynos_g2d_drm.h perhaps ?) and make sure exynos_drm.h includes the
>> new header
>>   - if neither of these are possible, then please ensure that the new
>> header uses correct types (see the docs [1]), use MIT/X11 license (if
>> possible) and link where upstream userspace is happy with the
>> interface (ideally more than a simple test app like libdrm)
>
>
> Whops... you have provided the third choice, nice  :-D
>
> And I got little idea about license, where should I use the MIT/X11
> license, should I declare the MIT/X11 license in kernel uapi head
> file, but Andreas just remind that kernel do not allow to no GUN
> license. Or may be I can:
Now that's a lovely typo - (GNU vs GUN) :-)

But seriously - what makes you think that the kernel does not allow
MIT/X11 licensed code ? Most of the DRM subsystem uses it.

> 1. Use GUN license in kernel rockchip_drm.h uapi head file
> 2. Use MIT/X11 license in libdrm rockchip_drm.h head file.
>
I would suggest keeping the license the same in both places (the
libdrm ones should be a direct copy of the kernel one produced with
`make headers_install`), regardless of which one you opt for.

> And I don't understand the "link where upstream userspace is happy
> with the interface", could you reference small example here.
>
Already mentioned elsewhere but for posterity:

If designing a new interface one should provide a reference to a
maintained upstream project, where the design was approved. Reason
being is that unlike ChromeOS's kernel upstream one gets to keep its
interfaces forever. And yes, I realise that CrOS folks are trying
really hard to upstream things and use vanilla kernel.

Regards,
Emil

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 2/4] drm: rockchip: add RGA driver support
@ 2016-03-30 18:34     ` Rob Clark
  0 siblings, 0 replies; 73+ messages in thread
From: Rob Clark @ 2016-03-30 18:34 UTC (permalink / raw)
  To: Yakir Yang
  Cc: David Airlie, Mark Yao, Heiko Stuebner, devicetree, Russell King,
	Pawel Moll, Ian Campbell, Linux Kernel Mailing List, dri-devel,
	open list:ARM/Rockchip SoC...,
	Rob Herring, Kumar Gala, linux-arm-kernel, Emil Velikov

On Mon, Mar 21, 2016 at 5:40 AM, Yakir Yang <ykk@rock-chips.com> wrote:
> Rockchip RGA is a separate 2D raster graphic acceleration unit. It
> accelerates 2D graphics operations, such as point/line drawing, image
> scaling, rotation, BitBLT, alpha blending and image blur/sharpness.
>
> The RGA driver is based on Exynos G2D driver, it is performed by two
> tasks simply.
> 1. Configures the rendering parameters, such as foreground color and
>    coordinates data by setting the drawing context registers.
> 2. Start the rendering process by calling rga_exec() ioctl.
>
> The RGA supports DMA mode as host interface. User can make command list
> to reduce HOST(ARM) loads. The contents of The command list is setted to
> relevant registers of RGA by DMA.
>
> The command list is composed Header and command sets and Tail.
> - Header: The number of command set(4Bytes)
> - Command set: Register offset(4Bytes) + Register data(4Bytes)
> - Tail: Pointer of base address of the other command list(4Bytes)
>
> By Tail field, the G2D can process many command lists without halt at
> one go.
>
> The G2D has following the rendering pipeline.
>                --->     Color Fill     --->
>                |                          |
> --> DMA (read) ---> Src Bitmap Process ----> Alpha/ROP ---> Format convert ---> DMA (Write)
>                |                          |
>                ---> Dst Bitmap Process --->
>
> And supports various operations from the rendering pipeline.
> - copy
> - fast solid color fill
> - rotation
> - flip
> - 4 operand raster operation(ROP4)
> - alpha blending
> - color key
> - dithering
> - etc
>
> User should make the command list to data and registers needed by
> operation to use. The Rockchip RGA driver only manages the command lists
> received from user. Some registers needs memory base address(physical
> address) of image. User doesn't know its physical address, so fills the
> gem handle of that memory than address to command sets, then RGA driver
> converts it to memory base address.
>
> We adds three ioctls for Rockchip RGA.
>
> - ioctls
> DRM_ROCKCHIP_RGA_GET_VER: get the RGA hardware version
> DRM_ROCKCHIP_RGA_SET_CMDLIST: set the command list from user to driver
> DRM_ROCKCHIP_RGA_EXEC: execute the command lists setted to driver

ok, so from a quick look at this (translation: correct me if I'm
wrong, I may be missunderstanding things)

1) it looks like you have a mmu/iommu (which is good, if hw isn't
getting programmed w/ physical addresses then less likely that
cmdstream validation is needed.. unless the mmu can be reprogrammed
from cmdstream?)

2) it looks like you can queue up work and some sort of "command
processor" processes the queued up packets asynchronously from the
cpu, which is also good.. since it's really easy to make 2d accel
slower than cpu, and you really want userspace to be able to continue
asynchronously from hw building up new cmdstream while hw is chewing
on existing ones..

so, assuming I'm not too far off base with that, I think it is strange
for EXEC ioctl to block until completion.  I suspect instead you want
to return a fence (which for now could just be a pipe specific seqno,
although support for fence fd's would be an obvious future extension),
and have a different ioctl that could block until the fence is
completed[1].  (So perhaps have a look at freedreno and etnaviv UAPI
more than exynos g2d.)

Also, not sure if you could submit multiple different blits in one
go..  in particular w/ switching src/dst/op.  If not, you might want
to be able to submit N cmdbufs in one ioctl.

What I'm getting with in all of this, is if you look at how, for
example, glyph rendering works in x11, there will be a whole lot of
small blit ops each glyph sized.  (So maybe less than 20x20 pixels.)
For that sort of use case you really want to queue up as many as you
can, rather than doing an ioctl call for each.

I think the suggesion on the cover-letter thread about implementing
EXA support for xf86-video-armsoc (or -rockchip if there is such a
thing) is a *really* good idea.  Not just to have a real-world
userspace consumer of the API, but also to help identify all the
things you are going to want to change about the UAPI to get decent
performance ;-)

BR,
-R

[1] see PrepareAccess/FinishAccess hooks in EXA for times when CPU
access to a buffer is needed

> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> ---
>  .../bindings/display/rockchip/rockchip-rga.txt     |  36 +
>  drivers/gpu/drm/rockchip/Kconfig                   |   9 +
>  drivers/gpu/drm/rockchip/Makefile                  |   1 +
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c        |  35 +-
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.h        |   4 +
>  drivers/gpu/drm/rockchip/rockchip_drm_rga.c        | 977 +++++++++++++++++++++
>  drivers/gpu/drm/rockchip/rockchip_drm_rga.h        | 108 +++
>  include/uapi/drm/rockchip_drm.h                    |  63 ++
>  8 files changed, 1232 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
>  create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.c
>  create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.h
>  create mode 100644 include/uapi/drm/rockchip_drm.h
>
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
> new file mode 100644
> index 0000000..0c606cb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
> @@ -0,0 +1,36 @@
> +device-tree bindings for rockchip 2D raster graphic acceleration controller (RGA)
> +
> +RGA is a separate 2D raster graphic acceleration unit. It accelerates 2D
> +graphics operations, such as point/line drawing, image scaling, rotation,
> +BitBLT, alpha blending and image blur/sharpness.
> +
> +Required properties:
> +- compatible: value should be one of the following
> +               "rockchip,rk3228-rga";
> +               "rockchip,rk3288-rga";
> +               "rockchip,rk3399-rga";
> +
> +- interrupts: RGA interrupt number.
> +
> +- clocks: phandle to RGA sclk/hclk/aclk clocks
> +
> +- clock-names: should be "aclk" "hclk" and "sclk"
> +
> +- resets: Must contain an entry for each entry in reset-names.
> +  See ../reset/reset.txt for details.
> +- reset-names: should be "aclk" "hclk" and "sclk"
> +
> +Example:
> +SoC specific DT entry:
> +       rga: rga@ff680000 {
> +               compatible = "rockchip,rk3399-rga";
> +               reg = <0xff680000 0x10000>;
> +               interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
> +               interrupt-names = "rga";
> +               clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>;
> +               clock-names = "aclk", "hclk", "sclk";
> +
> +               resets = <&cru SRST_A_RGA>, <&cru SRST_H_RGA>, <&cru SRST_RGA_CORE>;
> +               reset-names = "aclk", "hclk", "sclk";
> +               status = "disabled";
> +       };
> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> index 76b3362..220221b 100644
> --- a/drivers/gpu/drm/rockchip/Kconfig
> +++ b/drivers/gpu/drm/rockchip/Kconfig
> @@ -16,6 +16,15 @@ config DRM_ROCKCHIP
>           2D or 3D acceleration; acceleration is performed by other
>           IP found on the SoC.
>
> +config ROCKCHIP_DRM_RGA
> +       tristate "Rockchip RGA support"
> +       depends on DRM_ROCKCHIP
> +       help
> +         Choose this option to enable support for Rockchip RGA.
> +         Rockchip RGA is a kind of hardware 2D accelerator, and it support
> +         solid roration, scaling, color format transform, say Y to enable its
> +         driver
> +
>  config ROCKCHIP_DW_HDMI
>          tristate "Rockchip specific extensions for Synopsys DW HDMI"
>          depends on DRM_ROCKCHIP
> diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
> index df8fbef..7de547c 100644
> --- a/drivers/gpu/drm/rockchip/Makefile
> +++ b/drivers/gpu/drm/rockchip/Makefile
> @@ -9,5 +9,6 @@ rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
>  obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
>  obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
>  obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
> +obj-$(CONFIG_ROCKCHIP_DRM_RGA) += rockchip_drm_rga.o
>
>  obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_vop_reg.o
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> index 4e0feb2..1638bc9 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -25,10 +25,13 @@
>  #include <linux/of_graph.h>
>  #include <linux/component.h>
>
> +#include <drm/rockchip_drm.h>
> +
>  #include "rockchip_drm_drv.h"
>  #include "rockchip_drm_fb.h"
>  #include "rockchip_drm_fbdev.h"
>  #include "rockchip_drm_gem.h"
> +#include "rockchip_drm_rga.h"
>
>  #define DRIVER_NAME    "rockchip"
>  #define DRIVER_DESC    "RockChip Soc DRM"
> @@ -277,16 +280,28 @@ EXPORT_SYMBOL_GPL(rockchip_unregister_subdrv);
>
>  static int rockchip_drm_open(struct drm_device *dev, struct drm_file *file)
>  {
> +       struct rockchip_drm_file_private *file_priv;
>         struct drm_rockchip_subdrv *subdrv;
>         int ret = 0;
>
> +       file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
> +       if (!file_priv)
> +               return -ENOMEM;
> +
> +       file->driver_priv = file_priv;
> +
>         list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list) {
>                 ret = subdrv->open(dev, subdrv->dev, file);
>                 if (ret)
> -                       return ret;
> +                       goto err_file_priv_free;
>         }
>
>         return 0;
> +
> +err_file_priv_free:
> +       kfree(file_priv);
> +       file->driver_priv = NULL;
> +       return ret;
>  }
>
>  static void rockchip_drm_preclose(struct drm_device *dev,
> @@ -298,6 +313,12 @@ static void rockchip_drm_preclose(struct drm_device *dev,
>                 subdrv->close(dev, subdrv->dev, file);
>  }
>
> +static void rockchip_drm_postclose(struct drm_device *dev,
> +                                  struct drm_file *file)
> +{
> +       kfree(file->driver_priv);
> +}
> +
>  void rockchip_drm_lastclose(struct drm_device *dev)
>  {
>         struct rockchip_drm_private *priv = dev->dev_private;
> @@ -305,6 +326,15 @@ void rockchip_drm_lastclose(struct drm_device *dev)
>         drm_fb_helper_restore_fbdev_mode_unlocked(&priv->fbdev_helper);
>  }
>
> +static const struct drm_ioctl_desc rockchip_ioctls[] = {
> +       DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_GET_VER, rockchip_rga_get_ver_ioctl,
> +                         DRM_AUTH | DRM_RENDER_ALLOW),
> +       DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_SET_CMDLIST, rockchip_rga_set_cmdlist_ioctl,
> +                         DRM_AUTH | DRM_RENDER_ALLOW),
> +       DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_EXEC, rockchip_rga_exec_ioctl,
> +                         DRM_AUTH | DRM_RENDER_ALLOW),
> +};
> +
>  static const struct file_operations rockchip_drm_driver_fops = {
>         .owner = THIS_MODULE,
>         .open = drm_open,
> @@ -330,6 +360,7 @@ static struct drm_driver rockchip_drm_driver = {
>         .unload                 = rockchip_drm_unload,
>         .open                   = rockchip_drm_open,
>         .preclose               = rockchip_drm_preclose,
> +       .postclose              = rockchip_drm_postclose,
>         .lastclose              = rockchip_drm_lastclose,
>         .get_vblank_counter     = drm_vblank_no_hw_counter,
>         .enable_vblank          = rockchip_drm_crtc_enable_vblank,
> @@ -347,6 +378,8 @@ static struct drm_driver rockchip_drm_driver = {
>         .gem_prime_vmap         = rockchip_gem_prime_vmap,
>         .gem_prime_vunmap       = rockchip_gem_prime_vunmap,
>         .gem_prime_mmap         = rockchip_gem_mmap_buf,
> +       .ioctls                 = rockchip_ioctls,
> +       .num_ioctls             = ARRAY_SIZE(rockchip_ioctls),
>         .fops                   = &rockchip_drm_driver_fops,
>         .name   = DRIVER_NAME,
>         .desc   = DRIVER_DESC,
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> index 5ea5fcb..ea30ba6 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> @@ -53,6 +53,10 @@ struct drm_rockchip_subdrv {
>                       struct drm_file *file);
>  };
>
> +struct rockchip_drm_file_private {
> +       struct rockchip_drm_rga_private *rga_priv;
> +};
> +
>  struct rockchip_atomic_commit {
>         struct work_struct      work;
>         struct drm_atomic_state *state;
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_rga.c b/drivers/gpu/drm/rockchip/rockchip_drm_rga.c
> new file mode 100644
> index 0000000..4202121
> --- /dev/null
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_rga.c
> @@ -0,0 +1,977 @@
> +/*
> + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
> + * Author: Yakir Yang <ykk@rock-chips.com>
> + *
> + * based on exynos_drm_g2d.c
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/debugfs.h>
> +#include <linux/delay.h>
> +#include <linux/dma-buf.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/interrupt.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/reset.h>
> +#include <linux/seq_file.h>
> +#include <linux/slab.h>
> +#include <linux/uaccess.h>
> +
> +#include <asm/cacheflush.h>
> +#include <drm/drmP.h>
> +#include <drm/rockchip_drm.h>
> +
> +#include "rockchip_drm_drv.h"
> +#include "rockchip_drm_rga.h"
> +
> +#define RGA_MODE_BASE_REG              0x0100
> +#define RGA_MODE_MAX_REG               0x017C
> +
> +#define RGA_SYS_CTRL                   0x0000
> +#define RGA_CMD_CTRL                   0x0004
> +#define RGA_CMD_BASE                   0x0008
> +#define RGA_INT                                0x0010
> +#define RGA_MMU_CTRL0                  0x0014
> +#define RGA_VERSION_INFO               0x0028
> +
> +#define RGA_SRC_Y_RGB_BASE_ADDR                0x0108
> +#define RGA_SRC_CB_BASE_ADDR           0x010C
> +#define RGA_SRC_CR_BASE_ADDR           0x0110
> +#define RGA_SRC1_RGB_BASE_ADDR         0x0114
> +#define RGA_DST_Y_RGB_BASE_ADDR                0x013C
> +#define RGA_DST_CB_BASE_ADDR           0x0140
> +#define RGA_DST_CR_BASE_ADDR           0x014C
> +#define RGA_MMU_CTRL1                  0x016C
> +#define RGA_MMU_SRC_BASE               0x0170
> +#define RGA_MMU_SRC1_BASE              0x0174
> +#define RGA_MMU_DST_BASE               0x0178
> +
> +static void rga_dma_flush_range(void *ptr, int size)
> +{
> +#ifdef CONFIG_ARM
> +       dmac_flush_range(ptr, ptr + size);
> +       outer_flush_range(virt_to_phys(ptr), virt_to_phys(ptr + size));
> +#elif CONFIG_ARM64
> +       __dma_flush_range(ptr, ptr + size);
> +#endif
> +}
> +
> +static inline void rga_write(struct rockchip_rga *rga, u32 reg, u32 value)
> +{
> +       writel(value, rga->regs + reg);
> +}
> +
> +static inline u32 rga_read(struct rockchip_rga *rga, u32 reg)
> +{
> +       return readl(rga->regs + reg);
> +}
> +
> +static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
> +{
> +       u32 temp = rga_read(rga, reg) & ~(mask);
> +
> +       temp |= val & mask;
> +       rga_write(rga, reg, temp);
> +}
> +
> +static int rga_enable_clocks(struct rockchip_rga *rga)
> +{
> +       int ret;
> +
> +       ret = clk_prepare_enable(rga->sclk);
> +       if (ret) {
> +               dev_err(rga->dev, "Cannot enable rga sclk: %d\n", ret);
> +               return ret;
> +       }
> +
> +       ret = clk_prepare_enable(rga->aclk);
> +       if (ret) {
> +               dev_err(rga->dev, "Cannot enable rga aclk: %d\n", ret);
> +               goto err_disable_sclk;
> +       }
> +
> +       ret = clk_prepare_enable(rga->hclk);
> +       if (ret) {
> +               dev_err(rga->dev, "Cannot enable rga hclk: %d\n", ret);
> +               goto err_disable_aclk;
> +       }
> +
> +       return 0;
> +
> +err_disable_sclk:
> +       clk_disable_unprepare(rga->sclk);
> +err_disable_aclk:
> +       clk_disable_unprepare(rga->aclk);
> +
> +       return ret;
> +}
> +
> +static void rga_disable_clocks(struct rockchip_rga *rga)
> +{
> +       clk_disable_unprepare(rga->sclk);
> +       clk_disable_unprepare(rga->hclk);
> +       clk_disable_unprepare(rga->aclk);
> +}
> +
> +static void rga_init_cmdlist(struct rockchip_rga *rga)
> +{
> +       struct rga_cmdlist_node *node;
> +       int nr;
> +
> +       node = rga->cmdlist_node;
> +
> +       for (nr = 0; nr < ARRAY_SIZE(rga->cmdlist_node); nr++)
> +               list_add_tail(&node[nr].list, &rga->free_cmdlist);
> +}
> +
> +static int rga_alloc_dma_buf_for_cmdlist(struct rga_runqueue_node *runqueue)
> +{
> +       struct list_head *run_cmdlist = &runqueue->run_cmdlist;
> +       struct device *dev = runqueue->dev;
> +       struct dma_attrs cmdlist_dma_attrs;
> +       struct rga_cmdlist_node *node;
> +       void *cmdlist_pool_virt;
> +       dma_addr_t cmdlist_pool;
> +       int cmdlist_cnt = 0;
> +       int count = 0;
> +
> +       list_for_each_entry(node, run_cmdlist, list)
> +               cmdlist_cnt++;
> +
> +       init_dma_attrs(&cmdlist_dma_attrs);
> +       dma_set_attr(DMA_ATTR_WRITE_COMBINE, &runqueue->cmdlist_dma_attrs);
> +
> +       cmdlist_pool_virt = dma_alloc_attrs(dev, cmdlist_cnt * RGA_CMDLIST_SIZE,
> +                                           &cmdlist_pool, GFP_KERNEL,
> +                                           &cmdlist_dma_attrs);
> +       if (!cmdlist_pool_virt) {
> +               dev_err(dev, "failed to allocate cmdlist dma memory\n");
> +               return -ENOMEM;
> +       }
> +
> +       /*
> +        * Fill in the RGA operation registers from cmdlist command buffer,
> +        * and also filled in the MMU TLB base information.
> +        */
> +       list_for_each_entry(node, run_cmdlist, list) {
> +               struct rga_cmdlist *cmdlist = &node->cmdlist;
> +               unsigned int mmu_ctrl = 0;
> +               unsigned int *dest;
> +               unsigned int reg;
> +               int i;
> +
> +               dest = cmdlist_pool_virt + RGA_CMDLIST_SIZE * 4 * count++;
> +
> +               for (i = 0; i < cmdlist->last / 2; i++) {
> +                       reg = (node->cmdlist.data[2 * i] - RGA_MODE_BASE_REG);
> +                       if (reg > RGA_MODE_BASE_REG)
> +                               continue;
> +                       dest[reg << 2] = cmdlist->data[2 * i + 1];
> +               }
> +
> +               if (cmdlist->src_mmu_pages) {
> +                       reg = RGA_MMU_SRC_BASE - RGA_MODE_BASE_REG;
> +                       dest[reg << 2] = virt_to_phys(cmdlist->src_mmu_pages) >> 4;
> +                       mmu_ctrl |= 0x7;
> +               }
> +
> +               if (cmdlist->dst_mmu_pages) {
> +                       reg = RGA_MMU_DST_BASE - RGA_MODE_BASE_REG;
> +                       dest[reg << 2] = virt_to_phys(cmdlist->dst_mmu_pages) >> 4;
> +                       mmu_ctrl |= 0x7 << 8;
> +               }
> +
> +               if (cmdlist->src1_mmu_pages) {
> +                       reg = RGA_MMU_SRC1_BASE - RGA_MODE_BASE_REG;
> +                       dest[reg << 2] = virt_to_phys(cmdlist->src1_mmu_pages) >> 4;
> +                       mmu_ctrl |= 0x7 << 4;
> +               }
> +
> +               reg = RGA_MMU_CTRL1 - RGA_MODE_BASE_REG;
> +               dest[reg << 2] = mmu_ctrl;
> +       }
> +
> +       rga_dma_flush_range(cmdlist_pool_virt, cmdlist_cnt * RGA_CMDLIST_SIZE);
> +
> +       runqueue->cmdlist_dma_attrs = cmdlist_dma_attrs;
> +       runqueue->cmdlist_pool_virt = cmdlist_pool_virt;
> +       runqueue->cmdlist_pool = cmdlist_pool;
> +       runqueue->cmdlist_cnt = cmdlist_cnt;
> +
> +       return 0;
> +}
> +
> +static int rga_check_reg_offset(struct device *dev,
> +                               struct rga_cmdlist_node *node)
> +{
> +       struct rga_cmdlist *cmdlist = &node->cmdlist;
> +       int index;
> +       int reg;
> +       int i;
> +
> +       for (i = 0; i < cmdlist->last / 2; i++) {
> +               index = cmdlist->last - 2 * (i + 1);
> +               reg = cmdlist->data[index];
> +
> +               switch (reg) {
> +               case RGA_BUF_TYPE_GEMFD | RGA_DST_Y_RGB_BASE_ADDR:
> +               case RGA_BUF_TYPE_GEMFD | RGA_SRC_Y_RGB_BASE_ADDR:
> +                       break;
> +
> +               case RGA_BUF_TYPE_USERPTR | RGA_DST_Y_RGB_BASE_ADDR:
> +               case RGA_BUF_TYPE_USERPTR | RGA_SRC_Y_RGB_BASE_ADDR:
> +                       goto err;
> +
> +               default:
> +                       if (reg < RGA_MODE_BASE_REG || reg > RGA_MODE_MAX_REG)
> +                               goto err;
> +
> +                       if (reg % 4)
> +                               goto err;
> +               }
> +       }
> +
> +       return 0;
> +
> +err:
> +       dev_err(dev, "Bad register offset: 0x%lx\n", cmdlist->data[index]);
> +       return -EINVAL;
> +}
> +
> +static struct dma_buf_attachment *
> +rga_gem_buf_to_pages(struct rockchip_rga *rga, void **mmu_pages, int fd)
> +{
> +       struct dma_buf_attachment *attach;
> +       struct dma_buf *dmabuf;
> +       struct sg_table *sgt;
> +       struct scatterlist *sgl;
> +       unsigned int mapped_size = 0;
> +       unsigned int address;
> +       unsigned int len;
> +       unsigned int i, p;
> +       unsigned int *pages;
> +       int ret;
> +
> +       dmabuf = dma_buf_get(fd);
> +       if (IS_ERR(dmabuf)) {
> +               dev_err(rga->dev, "Failed to get dma_buf with fd %d\n", fd);
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       attach = dma_buf_attach(dmabuf, rga->dev);
> +       if (IS_ERR(attach)) {
> +               dev_err(rga->dev, "Failed to attach dma_buf\n");
> +               ret = PTR_ERR(attach);
> +               goto failed_attach;
> +       }
> +
> +       sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
> +       if (IS_ERR(sgt)) {
> +               dev_err(rga->dev, "Failed to map dma_buf attachment\n");
> +               ret = PTR_ERR(sgt);
> +               goto failed_detach;
> +       }
> +
> +       /*
> +        * Alloc (2^3 * 4K) = 32K byte for storing pages, those space could
> +        * cover 32K * 4K = 128M ram address.
> +        */
> +       pages = (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
> +
> +       for_each_sg(sgt->sgl, sgl, sgt->nents, i) {
> +               len = sg_dma_len(sgl) >> PAGE_SHIFT;
> +               address = sg_phys(sgl);
> +
> +               for (p = 0; p < len; p++) {
> +                       dma_addr_t phys = address + (p << PAGE_SHIFT);
> +                       void *virt = phys_to_virt(phys);
> +
> +                       rga_dma_flush_range(virt, 4 * 1024);
> +                       pages[mapped_size + p] = phys;
> +               }
> +
> +               mapped_size += len;
> +       }
> +
> +       rga_dma_flush_range(pages, 32 * 1024);
> +
> +       *mmu_pages = pages;
> +
> +       dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
> +
> +       return attach;
> +
> +failed_detach:
> +       dma_buf_detach(dmabuf, attach);
> +failed_attach:
> +       dma_buf_put(dmabuf);
> +
> +       return ERR_PTR(ret);
> +}
> +
> +static int rga_map_cmdlist_gem(struct rockchip_rga *rga,
> +                              struct rga_cmdlist_node *node,
> +                              struct drm_device *drm_dev,
> +                              struct drm_file *file)
> +{
> +       struct rga_cmdlist *cmdlist = &node->cmdlist;
> +       struct dma_buf_attachment *attach;
> +       void *mmu_pages;
> +       int fd;
> +       int i;
> +
> +       for (i = 0; i < cmdlist->last / 2; i++) {
> +               int index = cmdlist->last - 2 * (i + 1);
> +
> +               switch (cmdlist->data[index]) {
> +               case RGA_SRC_Y_RGB_BASE_ADDR | RGA_BUF_TYPE_GEMFD:
> +                       fd = cmdlist->data[index + 1];
> +                       attach = rga_gem_buf_to_pages(rga, &mmu_pages, fd);
> +
> +                       cmdlist->src_attach = attach;
> +                       cmdlist->src_mmu_pages = mmu_pages;
> +                       break;
> +
> +               case RGA_DST_Y_RGB_BASE_ADDR | RGA_BUF_TYPE_GEMFD:
> +                       fd = cmdlist->data[index + 1];
> +                       attach = rga_gem_buf_to_pages(rga, &mmu_pages, fd);
> +
> +                       cmdlist->dst_attach = attach;
> +                       cmdlist->dst_mmu_pages = mmu_pages;
> +                       break;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static void rga_unmap_cmdlist_gem(struct rockchip_rga *rga,
> +                                 struct rga_cmdlist_node *node)
> +{
> +       struct dma_buf_attachment *attach;
> +       struct dma_buf *dma_buf;
> +
> +       attach = node->cmdlist.src_attach;
> +       if (attach) {
> +               dma_buf = attach->dmabuf;
> +               dma_buf_detach(dma_buf, attach);
> +               dma_buf_put(dma_buf);
> +       }
> +       node->cmdlist.src_attach = NULL;
> +
> +       attach = node->cmdlist.dst_attach;
> +       if (attach) {
> +               dma_buf = attach->dmabuf;
> +               dma_buf_detach(dma_buf, attach);
> +               dma_buf_put(dma_buf);
> +       }
> +       node->cmdlist.dst_attach = NULL;
> +
> +       if (node->cmdlist.src_mmu_pages)
> +               free_pages((unsigned long)node->cmdlist.src_mmu_pages, 3);
> +       node->cmdlist.src_mmu_pages = NULL;
> +
> +       if (node->cmdlist.src1_mmu_pages)
> +               free_pages((unsigned long)node->cmdlist.src1_mmu_pages, 3);
> +       node->cmdlist.src1_mmu_pages = NULL;
> +
> +       if (node->cmdlist.dst_mmu_pages)
> +               free_pages((unsigned long)node->cmdlist.dst_mmu_pages, 3);
> +       node->cmdlist.dst_mmu_pages = NULL;
> +}
> +
> +static void rga_cmd_start(struct rockchip_rga *rga,
> +                         struct rga_runqueue_node *runqueue)
> +{
> +       int ret;
> +
> +       ret = pm_runtime_get_sync(rga->dev);
> +       if (ret < 0)
> +               return;
> +
> +       rga_write(rga, RGA_SYS_CTRL, 0x00);
> +
> +       rga_write(rga, RGA_CMD_BASE, runqueue->cmdlist_pool);
> +
> +       rga_write(rga, RGA_SYS_CTRL, 0x22);
> +
> +       rga_write(rga, RGA_INT, 0x600);
> +
> +       rga_write(rga, RGA_CMD_CTRL, ((runqueue->cmdlist_cnt - 1) << 3) | 0x1);
> +}
> +
> +static void rga_free_runqueue_node(struct rockchip_rga *rga,
> +                                  struct rga_runqueue_node *runqueue)
> +{
> +       struct rga_cmdlist_node *node;
> +
> +       if (!runqueue)
> +               return;
> +
> +       if (runqueue->cmdlist_pool_virt && runqueue->cmdlist_pool)
> +               dma_free_attrs(rga->dev, runqueue->cmdlist_cnt * RGA_CMDLIST_SIZE,
> +                              runqueue->cmdlist_pool_virt,
> +                              runqueue->cmdlist_pool,
> +                              &runqueue->cmdlist_dma_attrs);
> +
> +       mutex_lock(&rga->cmdlist_mutex);
> +       /*
> +        * commands in run_cmdlist have been completed so unmap all gem
> +        * objects in each command node so that they are unreferenced.
> +        */
> +       list_for_each_entry(node, &runqueue->run_cmdlist, list)
> +               rga_unmap_cmdlist_gem(rga, node);
> +       list_splice_tail_init(&runqueue->run_cmdlist, &rga->free_cmdlist);
> +       mutex_unlock(&rga->cmdlist_mutex);
> +
> +       kmem_cache_free(rga->runqueue_slab, runqueue);
> +}
> +
> +static struct rga_runqueue_node *rga_get_runqueue(struct rockchip_rga *rga)
> +{
> +       struct rga_runqueue_node *runqueue;
> +
> +       if (list_empty(&rga->runqueue_list))
> +               return NULL;
> +
> +       runqueue = list_first_entry(&rga->runqueue_list,
> +                                   struct rga_runqueue_node, list);
> +       list_del_init(&runqueue->list);
> +
> +       return runqueue;
> +}
> +
> +static void rga_exec_runqueue(struct rockchip_rga *rga)
> +{
> +       rga->runqueue_node = rga_get_runqueue(rga);
> +       if (rga->runqueue_node)
> +               rga_cmd_start(rga, rga->runqueue_node);
> +}
> +
> +static struct rga_cmdlist_node *rga_get_cmdlist(struct rockchip_rga *rga)
> +{
> +       struct rga_cmdlist_node *node;
> +       struct device *dev = rga->dev;
> +
> +       mutex_lock(&rga->cmdlist_mutex);
> +       if (list_empty(&rga->free_cmdlist)) {
> +               dev_err(dev, "there is no free cmdlist\n");
> +               mutex_unlock(&rga->cmdlist_mutex);
> +               return NULL;
> +       }
> +
> +       node = list_first_entry(&rga->free_cmdlist,
> +                               struct rga_cmdlist_node, list);
> +       list_del_init(&node->list);
> +       mutex_unlock(&rga->cmdlist_mutex);
> +
> +       return node;
> +}
> +
> +static void rga_add_cmdlist_to_inuse(struct rockchip_drm_rga_private *rga_priv,
> +                                    struct rga_cmdlist_node *node)
> +{
> +       struct rga_cmdlist_node *lnode;
> +
> +       if (list_empty(&rga_priv->inuse_cmdlist))
> +               goto add_to_list;
> +
> +       /* this links to base address of new cmdlist */
> +       lnode = list_entry(rga_priv->inuse_cmdlist.prev,
> +                          struct rga_cmdlist_node, list);
> +
> +add_to_list:
> +       list_add_tail(&node->list, &rga_priv->inuse_cmdlist);
> +}
> +
> +/*
> + * IOCRL functions for userspace to get RGA version.
> + */
> +int rockchip_rga_get_ver_ioctl(struct drm_device *drm_dev, void *data,
> +                              struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
> +       struct drm_rockchip_rga_get_ver *ver = data;
> +       struct rockchip_rga *rga;
> +       struct device *dev;
> +
> +       if (!rga_priv)
> +               return -ENODEV;
> +
> +       dev = rga_priv->dev;
> +       if (!dev)
> +               return -ENODEV;
> +
> +       rga = dev_get_drvdata(dev);
> +       if (!rga)
> +               return -EFAULT;
> +
> +       ver->major = rga->version.major;
> +       ver->minor = rga->version.minor;
> +
> +       return 0;
> +}
> +
> +/*
> + * IOCRL functions for userspace to send an RGA request.
> + */
> +int rockchip_rga_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
> +                                  struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
> +       struct drm_rockchip_rga_set_cmdlist *req = data;
> +       struct rga_cmdlist_node *node;
> +       struct rga_cmdlist *cmdlist;
> +       struct rockchip_rga *rga;
> +       int ret;
> +
> +       if (!rga_priv)
> +               return -ENODEV;
> +
> +       if (!rga_priv->dev)
> +               return -ENODEV;
> +
> +       rga = dev_get_drvdata(rga_priv->dev);
> +       if (!rga)
> +               return -EFAULT;
> +
> +       node = rga_get_cmdlist(rga);
> +       if (!node)
> +               return -ENOMEM;
> +
> +       cmdlist = &node->cmdlist;
> +       cmdlist->last = 0;
> +
> +       if (req->cmd_nr > RGA_CMDLIST_SIZE || req->cmd_buf_nr > RGA_CMDBUF_SIZE) {
> +               dev_err(rga->dev, "cmdlist size is too big\n");
> +               return -EINVAL;
> +       }
> +
> +       /*
> +        * Copy the command / buffer registers setting from userspace, each
> +        * command have two integer, one for register offset, another for
> +        * register value.
> +        */
> +       if (copy_from_user((void *)cmdlist->data, (const void __user *)req->cmd,
> +                          sizeof(struct drm_rockchip_rga_cmd) * req->cmd_nr))
> +               return -EFAULT;
> +       cmdlist->last += req->cmd_nr * 2;
> +
> +       if (copy_from_user((void *)cmdlist->data + cmdlist->last,
> +                          (const void __user *)req->cmd_buf,
> +                          sizeof(struct drm_rockchip_rga_cmd) * req->cmd_buf_nr))
> +               return -EFAULT;
> +       cmdlist->last += req->cmd_buf_nr * 2;
> +
> +       /*
> +        * Check the userspace command registers, and mapping the framebuffer,
> +        * create the RGA mmu pages or get the framebuffer dma address.
> +        */
> +       ret = rga_check_reg_offset(rga->dev, node);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = rga_map_cmdlist_gem(rga, node, drm_dev, file);
> +       if (ret < 0)
> +               return ret;
> +
> +       rga_add_cmdlist_to_inuse(rga_priv, node);
> +
> +       return 0;
> +}
> +
> +/*
> + * IOCRL functions for userspace to start RGA transform.
> + */
> +int rockchip_rga_exec_ioctl(struct drm_device *drm_dev, void *data,
> +                           struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
> +       struct rga_runqueue_node *runqueue;
> +       struct rockchip_rga *rga;
> +       struct device *dev;
> +       int ret;
> +
> +       if (!rga_priv)
> +               return -ENODEV;
> +
> +       dev = rga_priv->dev;
> +       if (!dev)
> +               return -ENODEV;
> +
> +       rga = dev_get_drvdata(dev);
> +       if (!rga)
> +               return -EFAULT;
> +
> +       runqueue = kmem_cache_alloc(rga->runqueue_slab, GFP_KERNEL);
> +       if (!runqueue) {
> +               dev_err(rga->dev, "failed to allocate memory\n");
> +               return -ENOMEM;
> +       }
> +
> +       runqueue->dev = rga->dev;
> +
> +       init_completion(&runqueue->complete);
> +
> +       INIT_LIST_HEAD(&runqueue->run_cmdlist);
> +
> +       list_splice_init(&rga_priv->inuse_cmdlist, &runqueue->run_cmdlist);
> +
> +       if (list_empty(&runqueue->run_cmdlist)) {
> +               dev_err(rga->dev, "there is no inuse cmdlist\n");
> +               kmem_cache_free(rga->runqueue_slab, runqueue);
> +               return -EPERM;
> +       }
> +
> +       ret = rga_alloc_dma_buf_for_cmdlist(runqueue);
> +       if (ret < 0) {
> +               dev_err(rga->dev, "cmdlist init failed\n");
> +               return ret;
> +       }
> +
> +       mutex_lock(&rga->runqueue_mutex);
> +       runqueue->pid = current->pid;
> +       runqueue->file = file;
> +       list_add_tail(&runqueue->list, &rga->runqueue_list);
> +       if (!rga->runqueue_node)
> +               rga_exec_runqueue(rga);
> +       mutex_unlock(&rga->runqueue_mutex);
> +
> +       wait_for_completion(&runqueue->complete);
> +       rga_free_runqueue_node(rga, runqueue);
> +
> +       return 0;
> +}
> +
> +static int rockchip_rga_open(struct drm_device *drm_dev, struct device *dev,
> +                            struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv;
> +
> +       rga_priv = kzalloc(sizeof(*rga_priv), GFP_KERNEL);
> +       if (!rga_priv)
> +               return -ENOMEM;
> +
> +       rga_priv->dev = dev;
> +       file_priv->rga_priv = rga_priv;
> +
> +       INIT_LIST_HEAD(&rga_priv->inuse_cmdlist);
> +
> +       return 0;
> +}
> +
> +static void rockchip_rga_close(struct drm_device *drm_dev, struct device *dev,
> +                              struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
> +       struct rga_cmdlist_node *node, *n;
> +       struct rockchip_rga *rga;
> +
> +       if (!dev)
> +               return;
> +
> +       rga = dev_get_drvdata(dev);
> +       if (!rga)
> +               return;
> +
> +       mutex_lock(&rga->cmdlist_mutex);
> +       list_for_each_entry_safe(node, n, &rga_priv->inuse_cmdlist, list) {
> +               /*
> +                * unmap all gem objects not completed.
> +                *
> +                * P.S. if current process was terminated forcely then
> +                * there may be some commands in inuse_cmdlist so unmap
> +                * them.
> +                */
> +               rga_unmap_cmdlist_gem(rga, node);
> +               list_move_tail(&node->list, &rga->free_cmdlist);
> +       }
> +       mutex_unlock(&rga->cmdlist_mutex);
> +
> +       kfree(file_priv->rga_priv);
> +}
> +
> +static void rga_runqueue_worker(struct work_struct *work)
> +{
> +       struct rockchip_rga *rga = container_of(work, struct rockchip_rga,
> +                                           runqueue_work);
> +
> +       mutex_lock(&rga->runqueue_mutex);
> +       pm_runtime_put_sync(rga->dev);
> +
> +       complete(&rga->runqueue_node->complete);
> +
> +       if (rga->suspended)
> +               rga->runqueue_node = NULL;
> +       else
> +               rga_exec_runqueue(rga);
> +
> +       mutex_unlock(&rga->runqueue_mutex);
> +}
> +
> +static irqreturn_t rga_irq_handler(int irq, void *dev_id)
> +{
> +       struct rockchip_rga *rga = dev_id;
> +       int intr;
> +
> +       intr = rga_read(rga, RGA_INT) & 0xf;
> +
> +       rga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
> +
> +       if (intr & 0x04)
> +               queue_work(rga->rga_workq, &rga->runqueue_work);
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static int rga_parse_dt(struct rockchip_rga *rga)
> +{
> +       struct reset_control *sclk_rst, *aclk_rst, *hclk_rst;
> +
> +       sclk_rst = devm_reset_control_get(rga->dev, "sclk");
> +       if (IS_ERR(sclk_rst)) {
> +               dev_err(rga->dev, "failed to get sclk reset controller\n");
> +               return PTR_ERR(sclk_rst);
> +       }
> +
> +       aclk_rst = devm_reset_control_get(rga->dev, "aclk");
> +       if (IS_ERR(aclk_rst)) {
> +               dev_err(rga->dev, "failed to get aclk reset controller\n");
> +               return PTR_ERR(aclk_rst);
> +       }
> +
> +       hclk_rst = devm_reset_control_get(rga->dev, "hclk");
> +       if (IS_ERR(hclk_rst)) {
> +               dev_err(rga->dev, "failed to get hclk reset controller\n");
> +               return PTR_ERR(hclk_rst);
> +       }
> +
> +       reset_control_assert(sclk_rst);
> +       usleep_range(10, 20);
> +       reset_control_deassert(sclk_rst);
> +
> +       reset_control_assert(aclk_rst);
> +       usleep_range(10, 20);
> +       reset_control_deassert(aclk_rst);
> +
> +       reset_control_assert(hclk_rst);
> +       usleep_range(10, 20);
> +       reset_control_deassert(hclk_rst);
> +
> +       rga->sclk = devm_clk_get(rga->dev, "sclk");
> +       if (IS_ERR(rga->sclk)) {
> +               dev_err(rga->dev, "failed to get sclk clock\n");
> +               return PTR_ERR(rga->sclk);
> +       }
> +
> +       rga->aclk = devm_clk_get(rga->dev, "aclk");
> +       if (IS_ERR(rga->aclk)) {
> +               dev_err(rga->dev, "failed to get aclk clock\n");
> +               return PTR_ERR(rga->aclk);
> +       }
> +
> +       rga->hclk = devm_clk_get(rga->dev, "hclk");
> +       if (IS_ERR(rga->hclk)) {
> +               dev_err(rga->dev, "failed to get hclk clock\n");
> +               return PTR_ERR(rga->hclk);
> +       }
> +
> +       return rga_enable_clocks(rga);
> +}
> +
> +static const struct of_device_id rockchip_rga_dt_ids[] = {
> +       { .compatible = "rockchip,rk3288-rga", },
> +       { .compatible = "rockchip,rk3228-rga", },
> +       { .compatible = "rockchip,rk3399-rga", },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, rockchip_rga_dt_ids);
> +
> +static int rga_probe(struct platform_device *pdev)
> +{
> +       struct drm_rockchip_subdrv *subdrv;
> +       struct rockchip_rga *rga;
> +       struct resource *iores;
> +       int irq;
> +       int ret;
> +
> +       if (!pdev->dev.of_node)
> +               return -ENODEV;
> +
> +       rga = devm_kzalloc(&pdev->dev, sizeof(*rga), GFP_KERNEL);
> +       if (!rga)
> +               return -ENOMEM;
> +
> +       rga->dev = &pdev->dev;
> +
> +       rga->runqueue_slab = kmem_cache_create("rga_runqueue_slab",
> +                                              sizeof(struct rga_runqueue_node),
> +                                              0, 0, NULL);
> +       if (!rga->runqueue_slab)
> +               return -ENOMEM;
> +
> +       rga->rga_workq = create_singlethread_workqueue("rga");
> +       if (!rga->rga_workq) {
> +               dev_err(rga->dev, "failed to create workqueue\n");
> +               goto err_destroy_slab;
> +       }
> +
> +       INIT_WORK(&rga->runqueue_work, rga_runqueue_worker);
> +       INIT_LIST_HEAD(&rga->runqueue_list);
> +       mutex_init(&rga->runqueue_mutex);
> +
> +       INIT_LIST_HEAD(&rga->free_cmdlist);
> +       mutex_init(&rga->cmdlist_mutex);
> +
> +       rga_init_cmdlist(rga);
> +
> +       ret = rga_parse_dt(rga);
> +       if (ret) {
> +               dev_err(rga->dev, "Unable to parse OF data\n");
> +               goto err_destroy_workqueue;
> +       }
> +
> +       pm_runtime_enable(rga->dev);
> +
> +       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +       rga->regs = devm_ioremap_resource(rga->dev, iores);
> +       if (IS_ERR(rga->regs)) {
> +               ret = PTR_ERR(rga->regs);
> +               goto err_put_clk;
> +       }
> +
> +       irq = platform_get_irq(pdev, 0);
> +       if (irq < 0) {
> +               dev_err(rga->dev, "failed to get irq\n");
> +               ret = irq;
> +               goto err_put_clk;
> +       }
> +
> +       ret = devm_request_irq(rga->dev, irq, rga_irq_handler, 0,
> +                              dev_name(rga->dev), rga);
> +       if (ret < 0) {
> +               dev_err(rga->dev, "failed to request irq\n");
> +               goto err_put_clk;
> +       }
> +
> +       platform_set_drvdata(pdev, rga);
> +
> +       rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
> +       rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
> +
> +       subdrv = &rga->subdrv;
> +       subdrv->dev = rga->dev;
> +       subdrv->open = rockchip_rga_open;
> +       subdrv->close = rockchip_rga_close;
> +
> +       rockchip_register_subdrv(subdrv);
> +
> +       return 0;
> +
> +err_put_clk:
> +       pm_runtime_disable(rga->dev);
> +err_destroy_workqueue:
> +       destroy_workqueue(rga->rga_workq);
> +err_destroy_slab:
> +       kmem_cache_destroy(rga->runqueue_slab);
> +
> +       return ret;
> +}
> +
> +static int rga_remove(struct platform_device *pdev)
> +{
> +       struct rockchip_rga *rga = platform_get_drvdata(pdev);
> +
> +       cancel_work_sync(&rga->runqueue_work);
> +
> +       while (rga->runqueue_node) {
> +               rga_free_runqueue_node(rga, rga->runqueue_node);
> +               rga->runqueue_node = rga_get_runqueue(rga);
> +       }
> +
> +       rockchip_unregister_subdrv(&rga->subdrv);
> +
> +       return 0;
> +}
> +
> +static int rga_suspend(struct device *dev)
> +{
> +       struct rockchip_rga *rga = dev_get_drvdata(dev);
> +
> +       mutex_lock(&rga->runqueue_mutex);
> +       rga->suspended = true;
> +       mutex_unlock(&rga->runqueue_mutex);
> +
> +       flush_work(&rga->runqueue_work);
> +
> +       return 0;
> +}
> +
> +static int rga_resume(struct device *dev)
> +{
> +       struct rockchip_rga *rga = dev_get_drvdata(dev);
> +
> +       rga->suspended = false;
> +       rga_exec_runqueue(rga);
> +
> +       return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int rga_runtime_suspend(struct device *dev)
> +{
> +       struct rockchip_rga *rga = dev_get_drvdata(dev);
> +
> +       rga_disable_clocks(rga);
> +
> +       return 0;
> +}
> +
> +static int rga_runtime_resume(struct device *dev)
> +{
> +       struct rockchip_rga *rga = dev_get_drvdata(dev);
> +
> +       return rga_enable_clocks(rga);
> +}
> +#endif
> +
> +static const struct dev_pm_ops rga_pm = {
> +       SET_SYSTEM_SLEEP_PM_OPS(rga_suspend, rga_resume)
> +       SET_RUNTIME_PM_OPS(rga_runtime_suspend,
> +                          rga_runtime_resume, NULL)
> +};
> +
> +static struct platform_driver rga_pltfm_driver = {
> +       .probe  = rga_probe,
> +       .remove = rga_remove,
> +       .driver = {
> +               .name = "rockchip-rga",
> +               .pm = &rga_pm,
> +               .of_match_table = rockchip_rga_dt_ids,
> +       },
> +};
> +
> +module_platform_driver(rga_pltfm_driver);
> +
> +MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
> +MODULE_DESCRIPTION("Rockchip RGA Driver Extension");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:rockchip-rga");
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_rga.h b/drivers/gpu/drm/rockchip/rockchip_drm_rga.h
> new file mode 100644
> index 0000000..4a8839a
> --- /dev/null
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_rga.h
> @@ -0,0 +1,108 @@
> +#ifndef __ROCKCHIP_DRM_RGA__
> +#define __ROCKCHIP_DRM_RGA__
> +
> +#define RGA_CMDBUF_SIZE                        14
> +#define RGA_CMDLIST_SIZE               0x20
> +#define RGA_CMDLIST_NUM                        64
> +
> +/* cmdlist data structure */
> +struct rga_cmdlist {
> +       u32             head;
> +       unsigned long   data[RGA_CMDLIST_SIZE * 2];
> +       u32             last;   /* last data offset */
> +       void            *src_mmu_pages;
> +       void            *dst_mmu_pages;
> +       void            *src1_mmu_pages;
> +       struct dma_buf_attachment *src_attach;
> +       struct dma_buf_attachment *dst_attach;
> +};
> +
> +struct rga_cmdlist_node {
> +       struct list_head        list;
> +       struct rga_cmdlist      cmdlist;
> +};
> +
> +struct rga_runqueue_node {
> +       struct list_head        list;
> +
> +       struct device           *dev;
> +       pid_t                   pid;
> +       struct drm_file         *file;
> +       struct completion       complete;
> +
> +       struct list_head        run_cmdlist;
> +
> +       int                     cmdlist_cnt;
> +       void                    *cmdlist_pool_virt;
> +       dma_addr_t              cmdlist_pool;
> +       struct dma_attrs        cmdlist_dma_attrs;
> +};
> +
> +struct rockchip_rga_version {
> +       __u32                   major;
> +       __u32                   minor;
> +};
> +
> +struct rockchip_rga {
> +       struct drm_device       *drm_dev;
> +       struct device           *dev;
> +       struct regmap           *grf;
> +       void __iomem            *regs;
> +       struct clk              *sclk;
> +       struct clk              *aclk;
> +       struct clk              *hclk;
> +
> +       bool                            suspended;
> +       struct rockchip_rga_version     version;
> +       struct drm_rockchip_subdrv      subdrv;
> +       struct workqueue_struct         *rga_workq;
> +       struct work_struct              runqueue_work;
> +
> +       /* rga command list pool */
> +       struct rga_cmdlist_node         cmdlist_node[RGA_CMDLIST_NUM];
> +       struct mutex                    cmdlist_mutex;
> +
> +       struct list_head                free_cmdlist;
> +
> +       /* rga runqueue */
> +       struct rga_runqueue_node        *runqueue_node;
> +       struct list_head                runqueue_list;
> +       struct mutex                    runqueue_mutex;
> +       struct kmem_cache               *runqueue_slab;
> +};
> +
> +struct rockchip_drm_rga_private {
> +       struct device           *dev;
> +       struct list_head        inuse_cmdlist;
> +       struct list_head        userptr_list;
> +};
> +
> +#ifdef CONFIG_ROCKCHIP_DRM_RGA
> +int rockchip_rga_get_ver_ioctl(struct drm_device *dev, void *data,
> +                              struct drm_file *file_priv);
> +int rockchip_rga_set_cmdlist_ioctl(struct drm_device *dev, void *data,
> +                                  struct drm_file *file_priv);
> +int rockchip_rga_exec_ioctl(struct drm_device *dev, void *data,
> +                           struct drm_file *file_priv);
> +#else
> +static inline int rockchip_rga_get_ver_ioctl(struct drm_device *dev, void *data,
> +                                            struct drm_file *file_priv)
> +{
> +       return -ENODEV;
> +}
> +
> +static inline int rockchip_rga_set_cmdlist_ioctl(struct drm_device *dev,
> +                                                void *data,
> +                                                struct drm_file *file_priv)
> +{
> +       return -ENODEV;
> +}
> +
> +static inline int rockchip_rga_exec_ioctl(struct drm_device *dev, void *data,
> +                                         struct drm_file *file_priv)
> +{
> +       return -ENODEV;
> +}
> +#endif
> +
> +#endif /* __ROCKCHIP_DRM_RGA__ */
> diff --git a/include/uapi/drm/rockchip_drm.h b/include/uapi/drm/rockchip_drm.h
> new file mode 100644
> index 0000000..2e3e240
> --- /dev/null
> +++ b/include/uapi/drm/rockchip_drm.h
> @@ -0,0 +1,63 @@
> +/* rockchip_drm.h
> + *
> + * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd.
> + * Authors:
> + *     Yakir Yang <ykk@rock-chips.com>
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + */
> +
> +#ifndef _UAPI_ROCKCHIP_DRM_H_
> +#define _UAPI_ROCKCHIP_DRM_H_
> +
> +#include <drm/drm.h>
> +
> +struct drm_rockchip_rga_get_ver {
> +       __u32   major;
> +       __u32   minor;
> +};
> +
> +struct drm_rockchip_rga_cmd {
> +       __u32   offset;
> +       __u32   data;
> +};
> +
> +enum drm_rockchip_rga_buf_type {
> +       RGA_BUF_TYPE_USERPTR = 1 << 31,
> +       RGA_BUF_TYPE_GEMFD   = 1 << 30,
> +};
> +
> +struct drm_rockchip_rga_userptr {
> +       unsigned long userptr;
> +       unsigned long size;
> +};
> +
> +struct drm_rockchip_rga_set_cmdlist {
> +       __u64           cmd;
> +       __u64           cmd_buf;
> +       __u32           cmd_nr;
> +       __u32           cmd_buf_nr;
> +       __u64           user_data;
> +};
> +
> +struct drm_rockchip_rga_exec {
> +       __u64           async;
> +};
> +
> +#define DRM_ROCKCHIP_RGA_GET_VER               0x20
> +#define DRM_ROCKCHIP_RGA_SET_CMDLIST           0x21
> +#define DRM_ROCKCHIP_RGA_EXEC                  0x22
> +
> +#define DRM_IOCTL_ROCKCHIP_RGA_GET_VER         DRM_IOWR(DRM_COMMAND_BASE + \
> +       DRM_ROCKCHIP_RGA_GET_VER, struct drm_rockchip_rga_get_ver)
> +
> +#define DRM_IOCTL_ROCKCHIP_RGA_SET_CMDLIST     DRM_IOWR(DRM_COMMAND_BASE + \
> +       DRM_ROCKCHIP_RGA_SET_CMDLIST, struct drm_rockchip_rga_set_cmdlist)
> +
> +#define DRM_IOCTL_ROCKCHIP_RGA_EXEC            DRM_IOWR(DRM_COMMAND_BASE + \
> +       DRM_ROCKCHIP_RGA_EXEC, struct drm_rockchip_rga_exec)
> +
> +#endif /* _UAPI_ROCKCHIP_DRM_H */
> --
> 1.9.1
>
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 2/4] drm: rockchip: add RGA driver support
@ 2016-03-30 18:34     ` Rob Clark
  0 siblings, 0 replies; 73+ messages in thread
From: Rob Clark @ 2016-03-30 18:34 UTC (permalink / raw)
  To: Yakir Yang
  Cc: David Airlie, Mark Yao, Heiko Stuebner,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Russell King, Pawel Moll,
	Ian Campbell, Linux Kernel Mailing List,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	open list:ARM/Rockchip SoC...,
	Rob Herring, Kumar Gala,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Emil Velikov

On Mon, Mar 21, 2016 at 5:40 AM, Yakir Yang <ykk-TNX95d0MmH7DzftRWevZcw@public.gmane.org> wrote:
> Rockchip RGA is a separate 2D raster graphic acceleration unit. It
> accelerates 2D graphics operations, such as point/line drawing, image
> scaling, rotation, BitBLT, alpha blending and image blur/sharpness.
>
> The RGA driver is based on Exynos G2D driver, it is performed by two
> tasks simply.
> 1. Configures the rendering parameters, such as foreground color and
>    coordinates data by setting the drawing context registers.
> 2. Start the rendering process by calling rga_exec() ioctl.
>
> The RGA supports DMA mode as host interface. User can make command list
> to reduce HOST(ARM) loads. The contents of The command list is setted to
> relevant registers of RGA by DMA.
>
> The command list is composed Header and command sets and Tail.
> - Header: The number of command set(4Bytes)
> - Command set: Register offset(4Bytes) + Register data(4Bytes)
> - Tail: Pointer of base address of the other command list(4Bytes)
>
> By Tail field, the G2D can process many command lists without halt at
> one go.
>
> The G2D has following the rendering pipeline.
>                --->     Color Fill     --->
>                |                          |
> --> DMA (read) ---> Src Bitmap Process ----> Alpha/ROP ---> Format convert ---> DMA (Write)
>                |                          |
>                ---> Dst Bitmap Process --->
>
> And supports various operations from the rendering pipeline.
> - copy
> - fast solid color fill
> - rotation
> - flip
> - 4 operand raster operation(ROP4)
> - alpha blending
> - color key
> - dithering
> - etc
>
> User should make the command list to data and registers needed by
> operation to use. The Rockchip RGA driver only manages the command lists
> received from user. Some registers needs memory base address(physical
> address) of image. User doesn't know its physical address, so fills the
> gem handle of that memory than address to command sets, then RGA driver
> converts it to memory base address.
>
> We adds three ioctls for Rockchip RGA.
>
> - ioctls
> DRM_ROCKCHIP_RGA_GET_VER: get the RGA hardware version
> DRM_ROCKCHIP_RGA_SET_CMDLIST: set the command list from user to driver
> DRM_ROCKCHIP_RGA_EXEC: execute the command lists setted to driver

ok, so from a quick look at this (translation: correct me if I'm
wrong, I may be missunderstanding things)

1) it looks like you have a mmu/iommu (which is good, if hw isn't
getting programmed w/ physical addresses then less likely that
cmdstream validation is needed.. unless the mmu can be reprogrammed
from cmdstream?)

2) it looks like you can queue up work and some sort of "command
processor" processes the queued up packets asynchronously from the
cpu, which is also good.. since it's really easy to make 2d accel
slower than cpu, and you really want userspace to be able to continue
asynchronously from hw building up new cmdstream while hw is chewing
on existing ones..

so, assuming I'm not too far off base with that, I think it is strange
for EXEC ioctl to block until completion.  I suspect instead you want
to return a fence (which for now could just be a pipe specific seqno,
although support for fence fd's would be an obvious future extension),
and have a different ioctl that could block until the fence is
completed[1].  (So perhaps have a look at freedreno and etnaviv UAPI
more than exynos g2d.)

Also, not sure if you could submit multiple different blits in one
go..  in particular w/ switching src/dst/op.  If not, you might want
to be able to submit N cmdbufs in one ioctl.

What I'm getting with in all of this, is if you look at how, for
example, glyph rendering works in x11, there will be a whole lot of
small blit ops each glyph sized.  (So maybe less than 20x20 pixels.)
For that sort of use case you really want to queue up as many as you
can, rather than doing an ioctl call for each.

I think the suggesion on the cover-letter thread about implementing
EXA support for xf86-video-armsoc (or -rockchip if there is such a
thing) is a *really* good idea.  Not just to have a real-world
userspace consumer of the API, but also to help identify all the
things you are going to want to change about the UAPI to get decent
performance ;-)

BR,
-R

[1] see PrepareAccess/FinishAccess hooks in EXA for times when CPU
access to a buffer is needed

> Signed-off-by: Yakir Yang <ykk-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> ---
>  .../bindings/display/rockchip/rockchip-rga.txt     |  36 +
>  drivers/gpu/drm/rockchip/Kconfig                   |   9 +
>  drivers/gpu/drm/rockchip/Makefile                  |   1 +
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c        |  35 +-
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.h        |   4 +
>  drivers/gpu/drm/rockchip/rockchip_drm_rga.c        | 977 +++++++++++++++++++++
>  drivers/gpu/drm/rockchip/rockchip_drm_rga.h        | 108 +++
>  include/uapi/drm/rockchip_drm.h                    |  63 ++
>  8 files changed, 1232 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
>  create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.c
>  create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.h
>  create mode 100644 include/uapi/drm/rockchip_drm.h
>
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
> new file mode 100644
> index 0000000..0c606cb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
> @@ -0,0 +1,36 @@
> +device-tree bindings for rockchip 2D raster graphic acceleration controller (RGA)
> +
> +RGA is a separate 2D raster graphic acceleration unit. It accelerates 2D
> +graphics operations, such as point/line drawing, image scaling, rotation,
> +BitBLT, alpha blending and image blur/sharpness.
> +
> +Required properties:
> +- compatible: value should be one of the following
> +               "rockchip,rk3228-rga";
> +               "rockchip,rk3288-rga";
> +               "rockchip,rk3399-rga";
> +
> +- interrupts: RGA interrupt number.
> +
> +- clocks: phandle to RGA sclk/hclk/aclk clocks
> +
> +- clock-names: should be "aclk" "hclk" and "sclk"
> +
> +- resets: Must contain an entry for each entry in reset-names.
> +  See ../reset/reset.txt for details.
> +- reset-names: should be "aclk" "hclk" and "sclk"
> +
> +Example:
> +SoC specific DT entry:
> +       rga: rga@ff680000 {
> +               compatible = "rockchip,rk3399-rga";
> +               reg = <0xff680000 0x10000>;
> +               interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
> +               interrupt-names = "rga";
> +               clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>;
> +               clock-names = "aclk", "hclk", "sclk";
> +
> +               resets = <&cru SRST_A_RGA>, <&cru SRST_H_RGA>, <&cru SRST_RGA_CORE>;
> +               reset-names = "aclk", "hclk", "sclk";
> +               status = "disabled";
> +       };
> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> index 76b3362..220221b 100644
> --- a/drivers/gpu/drm/rockchip/Kconfig
> +++ b/drivers/gpu/drm/rockchip/Kconfig
> @@ -16,6 +16,15 @@ config DRM_ROCKCHIP
>           2D or 3D acceleration; acceleration is performed by other
>           IP found on the SoC.
>
> +config ROCKCHIP_DRM_RGA
> +       tristate "Rockchip RGA support"
> +       depends on DRM_ROCKCHIP
> +       help
> +         Choose this option to enable support for Rockchip RGA.
> +         Rockchip RGA is a kind of hardware 2D accelerator, and it support
> +         solid roration, scaling, color format transform, say Y to enable its
> +         driver
> +
>  config ROCKCHIP_DW_HDMI
>          tristate "Rockchip specific extensions for Synopsys DW HDMI"
>          depends on DRM_ROCKCHIP
> diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
> index df8fbef..7de547c 100644
> --- a/drivers/gpu/drm/rockchip/Makefile
> +++ b/drivers/gpu/drm/rockchip/Makefile
> @@ -9,5 +9,6 @@ rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
>  obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
>  obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
>  obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
> +obj-$(CONFIG_ROCKCHIP_DRM_RGA) += rockchip_drm_rga.o
>
>  obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_vop_reg.o
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> index 4e0feb2..1638bc9 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -25,10 +25,13 @@
>  #include <linux/of_graph.h>
>  #include <linux/component.h>
>
> +#include <drm/rockchip_drm.h>
> +
>  #include "rockchip_drm_drv.h"
>  #include "rockchip_drm_fb.h"
>  #include "rockchip_drm_fbdev.h"
>  #include "rockchip_drm_gem.h"
> +#include "rockchip_drm_rga.h"
>
>  #define DRIVER_NAME    "rockchip"
>  #define DRIVER_DESC    "RockChip Soc DRM"
> @@ -277,16 +280,28 @@ EXPORT_SYMBOL_GPL(rockchip_unregister_subdrv);
>
>  static int rockchip_drm_open(struct drm_device *dev, struct drm_file *file)
>  {
> +       struct rockchip_drm_file_private *file_priv;
>         struct drm_rockchip_subdrv *subdrv;
>         int ret = 0;
>
> +       file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
> +       if (!file_priv)
> +               return -ENOMEM;
> +
> +       file->driver_priv = file_priv;
> +
>         list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list) {
>                 ret = subdrv->open(dev, subdrv->dev, file);
>                 if (ret)
> -                       return ret;
> +                       goto err_file_priv_free;
>         }
>
>         return 0;
> +
> +err_file_priv_free:
> +       kfree(file_priv);
> +       file->driver_priv = NULL;
> +       return ret;
>  }
>
>  static void rockchip_drm_preclose(struct drm_device *dev,
> @@ -298,6 +313,12 @@ static void rockchip_drm_preclose(struct drm_device *dev,
>                 subdrv->close(dev, subdrv->dev, file);
>  }
>
> +static void rockchip_drm_postclose(struct drm_device *dev,
> +                                  struct drm_file *file)
> +{
> +       kfree(file->driver_priv);
> +}
> +
>  void rockchip_drm_lastclose(struct drm_device *dev)
>  {
>         struct rockchip_drm_private *priv = dev->dev_private;
> @@ -305,6 +326,15 @@ void rockchip_drm_lastclose(struct drm_device *dev)
>         drm_fb_helper_restore_fbdev_mode_unlocked(&priv->fbdev_helper);
>  }
>
> +static const struct drm_ioctl_desc rockchip_ioctls[] = {
> +       DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_GET_VER, rockchip_rga_get_ver_ioctl,
> +                         DRM_AUTH | DRM_RENDER_ALLOW),
> +       DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_SET_CMDLIST, rockchip_rga_set_cmdlist_ioctl,
> +                         DRM_AUTH | DRM_RENDER_ALLOW),
> +       DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_EXEC, rockchip_rga_exec_ioctl,
> +                         DRM_AUTH | DRM_RENDER_ALLOW),
> +};
> +
>  static const struct file_operations rockchip_drm_driver_fops = {
>         .owner = THIS_MODULE,
>         .open = drm_open,
> @@ -330,6 +360,7 @@ static struct drm_driver rockchip_drm_driver = {
>         .unload                 = rockchip_drm_unload,
>         .open                   = rockchip_drm_open,
>         .preclose               = rockchip_drm_preclose,
> +       .postclose              = rockchip_drm_postclose,
>         .lastclose              = rockchip_drm_lastclose,
>         .get_vblank_counter     = drm_vblank_no_hw_counter,
>         .enable_vblank          = rockchip_drm_crtc_enable_vblank,
> @@ -347,6 +378,8 @@ static struct drm_driver rockchip_drm_driver = {
>         .gem_prime_vmap         = rockchip_gem_prime_vmap,
>         .gem_prime_vunmap       = rockchip_gem_prime_vunmap,
>         .gem_prime_mmap         = rockchip_gem_mmap_buf,
> +       .ioctls                 = rockchip_ioctls,
> +       .num_ioctls             = ARRAY_SIZE(rockchip_ioctls),
>         .fops                   = &rockchip_drm_driver_fops,
>         .name   = DRIVER_NAME,
>         .desc   = DRIVER_DESC,
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> index 5ea5fcb..ea30ba6 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> @@ -53,6 +53,10 @@ struct drm_rockchip_subdrv {
>                       struct drm_file *file);
>  };
>
> +struct rockchip_drm_file_private {
> +       struct rockchip_drm_rga_private *rga_priv;
> +};
> +
>  struct rockchip_atomic_commit {
>         struct work_struct      work;
>         struct drm_atomic_state *state;
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_rga.c b/drivers/gpu/drm/rockchip/rockchip_drm_rga.c
> new file mode 100644
> index 0000000..4202121
> --- /dev/null
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_rga.c
> @@ -0,0 +1,977 @@
> +/*
> + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
> + * Author: Yakir Yang <ykk-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> + *
> + * based on exynos_drm_g2d.c
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/debugfs.h>
> +#include <linux/delay.h>
> +#include <linux/dma-buf.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/interrupt.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/reset.h>
> +#include <linux/seq_file.h>
> +#include <linux/slab.h>
> +#include <linux/uaccess.h>
> +
> +#include <asm/cacheflush.h>
> +#include <drm/drmP.h>
> +#include <drm/rockchip_drm.h>
> +
> +#include "rockchip_drm_drv.h"
> +#include "rockchip_drm_rga.h"
> +
> +#define RGA_MODE_BASE_REG              0x0100
> +#define RGA_MODE_MAX_REG               0x017C
> +
> +#define RGA_SYS_CTRL                   0x0000
> +#define RGA_CMD_CTRL                   0x0004
> +#define RGA_CMD_BASE                   0x0008
> +#define RGA_INT                                0x0010
> +#define RGA_MMU_CTRL0                  0x0014
> +#define RGA_VERSION_INFO               0x0028
> +
> +#define RGA_SRC_Y_RGB_BASE_ADDR                0x0108
> +#define RGA_SRC_CB_BASE_ADDR           0x010C
> +#define RGA_SRC_CR_BASE_ADDR           0x0110
> +#define RGA_SRC1_RGB_BASE_ADDR         0x0114
> +#define RGA_DST_Y_RGB_BASE_ADDR                0x013C
> +#define RGA_DST_CB_BASE_ADDR           0x0140
> +#define RGA_DST_CR_BASE_ADDR           0x014C
> +#define RGA_MMU_CTRL1                  0x016C
> +#define RGA_MMU_SRC_BASE               0x0170
> +#define RGA_MMU_SRC1_BASE              0x0174
> +#define RGA_MMU_DST_BASE               0x0178
> +
> +static void rga_dma_flush_range(void *ptr, int size)
> +{
> +#ifdef CONFIG_ARM
> +       dmac_flush_range(ptr, ptr + size);
> +       outer_flush_range(virt_to_phys(ptr), virt_to_phys(ptr + size));
> +#elif CONFIG_ARM64
> +       __dma_flush_range(ptr, ptr + size);
> +#endif
> +}
> +
> +static inline void rga_write(struct rockchip_rga *rga, u32 reg, u32 value)
> +{
> +       writel(value, rga->regs + reg);
> +}
> +
> +static inline u32 rga_read(struct rockchip_rga *rga, u32 reg)
> +{
> +       return readl(rga->regs + reg);
> +}
> +
> +static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
> +{
> +       u32 temp = rga_read(rga, reg) & ~(mask);
> +
> +       temp |= val & mask;
> +       rga_write(rga, reg, temp);
> +}
> +
> +static int rga_enable_clocks(struct rockchip_rga *rga)
> +{
> +       int ret;
> +
> +       ret = clk_prepare_enable(rga->sclk);
> +       if (ret) {
> +               dev_err(rga->dev, "Cannot enable rga sclk: %d\n", ret);
> +               return ret;
> +       }
> +
> +       ret = clk_prepare_enable(rga->aclk);
> +       if (ret) {
> +               dev_err(rga->dev, "Cannot enable rga aclk: %d\n", ret);
> +               goto err_disable_sclk;
> +       }
> +
> +       ret = clk_prepare_enable(rga->hclk);
> +       if (ret) {
> +               dev_err(rga->dev, "Cannot enable rga hclk: %d\n", ret);
> +               goto err_disable_aclk;
> +       }
> +
> +       return 0;
> +
> +err_disable_sclk:
> +       clk_disable_unprepare(rga->sclk);
> +err_disable_aclk:
> +       clk_disable_unprepare(rga->aclk);
> +
> +       return ret;
> +}
> +
> +static void rga_disable_clocks(struct rockchip_rga *rga)
> +{
> +       clk_disable_unprepare(rga->sclk);
> +       clk_disable_unprepare(rga->hclk);
> +       clk_disable_unprepare(rga->aclk);
> +}
> +
> +static void rga_init_cmdlist(struct rockchip_rga *rga)
> +{
> +       struct rga_cmdlist_node *node;
> +       int nr;
> +
> +       node = rga->cmdlist_node;
> +
> +       for (nr = 0; nr < ARRAY_SIZE(rga->cmdlist_node); nr++)
> +               list_add_tail(&node[nr].list, &rga->free_cmdlist);
> +}
> +
> +static int rga_alloc_dma_buf_for_cmdlist(struct rga_runqueue_node *runqueue)
> +{
> +       struct list_head *run_cmdlist = &runqueue->run_cmdlist;
> +       struct device *dev = runqueue->dev;
> +       struct dma_attrs cmdlist_dma_attrs;
> +       struct rga_cmdlist_node *node;
> +       void *cmdlist_pool_virt;
> +       dma_addr_t cmdlist_pool;
> +       int cmdlist_cnt = 0;
> +       int count = 0;
> +
> +       list_for_each_entry(node, run_cmdlist, list)
> +               cmdlist_cnt++;
> +
> +       init_dma_attrs(&cmdlist_dma_attrs);
> +       dma_set_attr(DMA_ATTR_WRITE_COMBINE, &runqueue->cmdlist_dma_attrs);
> +
> +       cmdlist_pool_virt = dma_alloc_attrs(dev, cmdlist_cnt * RGA_CMDLIST_SIZE,
> +                                           &cmdlist_pool, GFP_KERNEL,
> +                                           &cmdlist_dma_attrs);
> +       if (!cmdlist_pool_virt) {
> +               dev_err(dev, "failed to allocate cmdlist dma memory\n");
> +               return -ENOMEM;
> +       }
> +
> +       /*
> +        * Fill in the RGA operation registers from cmdlist command buffer,
> +        * and also filled in the MMU TLB base information.
> +        */
> +       list_for_each_entry(node, run_cmdlist, list) {
> +               struct rga_cmdlist *cmdlist = &node->cmdlist;
> +               unsigned int mmu_ctrl = 0;
> +               unsigned int *dest;
> +               unsigned int reg;
> +               int i;
> +
> +               dest = cmdlist_pool_virt + RGA_CMDLIST_SIZE * 4 * count++;
> +
> +               for (i = 0; i < cmdlist->last / 2; i++) {
> +                       reg = (node->cmdlist.data[2 * i] - RGA_MODE_BASE_REG);
> +                       if (reg > RGA_MODE_BASE_REG)
> +                               continue;
> +                       dest[reg << 2] = cmdlist->data[2 * i + 1];
> +               }
> +
> +               if (cmdlist->src_mmu_pages) {
> +                       reg = RGA_MMU_SRC_BASE - RGA_MODE_BASE_REG;
> +                       dest[reg << 2] = virt_to_phys(cmdlist->src_mmu_pages) >> 4;
> +                       mmu_ctrl |= 0x7;
> +               }
> +
> +               if (cmdlist->dst_mmu_pages) {
> +                       reg = RGA_MMU_DST_BASE - RGA_MODE_BASE_REG;
> +                       dest[reg << 2] = virt_to_phys(cmdlist->dst_mmu_pages) >> 4;
> +                       mmu_ctrl |= 0x7 << 8;
> +               }
> +
> +               if (cmdlist->src1_mmu_pages) {
> +                       reg = RGA_MMU_SRC1_BASE - RGA_MODE_BASE_REG;
> +                       dest[reg << 2] = virt_to_phys(cmdlist->src1_mmu_pages) >> 4;
> +                       mmu_ctrl |= 0x7 << 4;
> +               }
> +
> +               reg = RGA_MMU_CTRL1 - RGA_MODE_BASE_REG;
> +               dest[reg << 2] = mmu_ctrl;
> +       }
> +
> +       rga_dma_flush_range(cmdlist_pool_virt, cmdlist_cnt * RGA_CMDLIST_SIZE);
> +
> +       runqueue->cmdlist_dma_attrs = cmdlist_dma_attrs;
> +       runqueue->cmdlist_pool_virt = cmdlist_pool_virt;
> +       runqueue->cmdlist_pool = cmdlist_pool;
> +       runqueue->cmdlist_cnt = cmdlist_cnt;
> +
> +       return 0;
> +}
> +
> +static int rga_check_reg_offset(struct device *dev,
> +                               struct rga_cmdlist_node *node)
> +{
> +       struct rga_cmdlist *cmdlist = &node->cmdlist;
> +       int index;
> +       int reg;
> +       int i;
> +
> +       for (i = 0; i < cmdlist->last / 2; i++) {
> +               index = cmdlist->last - 2 * (i + 1);
> +               reg = cmdlist->data[index];
> +
> +               switch (reg) {
> +               case RGA_BUF_TYPE_GEMFD | RGA_DST_Y_RGB_BASE_ADDR:
> +               case RGA_BUF_TYPE_GEMFD | RGA_SRC_Y_RGB_BASE_ADDR:
> +                       break;
> +
> +               case RGA_BUF_TYPE_USERPTR | RGA_DST_Y_RGB_BASE_ADDR:
> +               case RGA_BUF_TYPE_USERPTR | RGA_SRC_Y_RGB_BASE_ADDR:
> +                       goto err;
> +
> +               default:
> +                       if (reg < RGA_MODE_BASE_REG || reg > RGA_MODE_MAX_REG)
> +                               goto err;
> +
> +                       if (reg % 4)
> +                               goto err;
> +               }
> +       }
> +
> +       return 0;
> +
> +err:
> +       dev_err(dev, "Bad register offset: 0x%lx\n", cmdlist->data[index]);
> +       return -EINVAL;
> +}
> +
> +static struct dma_buf_attachment *
> +rga_gem_buf_to_pages(struct rockchip_rga *rga, void **mmu_pages, int fd)
> +{
> +       struct dma_buf_attachment *attach;
> +       struct dma_buf *dmabuf;
> +       struct sg_table *sgt;
> +       struct scatterlist *sgl;
> +       unsigned int mapped_size = 0;
> +       unsigned int address;
> +       unsigned int len;
> +       unsigned int i, p;
> +       unsigned int *pages;
> +       int ret;
> +
> +       dmabuf = dma_buf_get(fd);
> +       if (IS_ERR(dmabuf)) {
> +               dev_err(rga->dev, "Failed to get dma_buf with fd %d\n", fd);
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       attach = dma_buf_attach(dmabuf, rga->dev);
> +       if (IS_ERR(attach)) {
> +               dev_err(rga->dev, "Failed to attach dma_buf\n");
> +               ret = PTR_ERR(attach);
> +               goto failed_attach;
> +       }
> +
> +       sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
> +       if (IS_ERR(sgt)) {
> +               dev_err(rga->dev, "Failed to map dma_buf attachment\n");
> +               ret = PTR_ERR(sgt);
> +               goto failed_detach;
> +       }
> +
> +       /*
> +        * Alloc (2^3 * 4K) = 32K byte for storing pages, those space could
> +        * cover 32K * 4K = 128M ram address.
> +        */
> +       pages = (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
> +
> +       for_each_sg(sgt->sgl, sgl, sgt->nents, i) {
> +               len = sg_dma_len(sgl) >> PAGE_SHIFT;
> +               address = sg_phys(sgl);
> +
> +               for (p = 0; p < len; p++) {
> +                       dma_addr_t phys = address + (p << PAGE_SHIFT);
> +                       void *virt = phys_to_virt(phys);
> +
> +                       rga_dma_flush_range(virt, 4 * 1024);
> +                       pages[mapped_size + p] = phys;
> +               }
> +
> +               mapped_size += len;
> +       }
> +
> +       rga_dma_flush_range(pages, 32 * 1024);
> +
> +       *mmu_pages = pages;
> +
> +       dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
> +
> +       return attach;
> +
> +failed_detach:
> +       dma_buf_detach(dmabuf, attach);
> +failed_attach:
> +       dma_buf_put(dmabuf);
> +
> +       return ERR_PTR(ret);
> +}
> +
> +static int rga_map_cmdlist_gem(struct rockchip_rga *rga,
> +                              struct rga_cmdlist_node *node,
> +                              struct drm_device *drm_dev,
> +                              struct drm_file *file)
> +{
> +       struct rga_cmdlist *cmdlist = &node->cmdlist;
> +       struct dma_buf_attachment *attach;
> +       void *mmu_pages;
> +       int fd;
> +       int i;
> +
> +       for (i = 0; i < cmdlist->last / 2; i++) {
> +               int index = cmdlist->last - 2 * (i + 1);
> +
> +               switch (cmdlist->data[index]) {
> +               case RGA_SRC_Y_RGB_BASE_ADDR | RGA_BUF_TYPE_GEMFD:
> +                       fd = cmdlist->data[index + 1];
> +                       attach = rga_gem_buf_to_pages(rga, &mmu_pages, fd);
> +
> +                       cmdlist->src_attach = attach;
> +                       cmdlist->src_mmu_pages = mmu_pages;
> +                       break;
> +
> +               case RGA_DST_Y_RGB_BASE_ADDR | RGA_BUF_TYPE_GEMFD:
> +                       fd = cmdlist->data[index + 1];
> +                       attach = rga_gem_buf_to_pages(rga, &mmu_pages, fd);
> +
> +                       cmdlist->dst_attach = attach;
> +                       cmdlist->dst_mmu_pages = mmu_pages;
> +                       break;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static void rga_unmap_cmdlist_gem(struct rockchip_rga *rga,
> +                                 struct rga_cmdlist_node *node)
> +{
> +       struct dma_buf_attachment *attach;
> +       struct dma_buf *dma_buf;
> +
> +       attach = node->cmdlist.src_attach;
> +       if (attach) {
> +               dma_buf = attach->dmabuf;
> +               dma_buf_detach(dma_buf, attach);
> +               dma_buf_put(dma_buf);
> +       }
> +       node->cmdlist.src_attach = NULL;
> +
> +       attach = node->cmdlist.dst_attach;
> +       if (attach) {
> +               dma_buf = attach->dmabuf;
> +               dma_buf_detach(dma_buf, attach);
> +               dma_buf_put(dma_buf);
> +       }
> +       node->cmdlist.dst_attach = NULL;
> +
> +       if (node->cmdlist.src_mmu_pages)
> +               free_pages((unsigned long)node->cmdlist.src_mmu_pages, 3);
> +       node->cmdlist.src_mmu_pages = NULL;
> +
> +       if (node->cmdlist.src1_mmu_pages)
> +               free_pages((unsigned long)node->cmdlist.src1_mmu_pages, 3);
> +       node->cmdlist.src1_mmu_pages = NULL;
> +
> +       if (node->cmdlist.dst_mmu_pages)
> +               free_pages((unsigned long)node->cmdlist.dst_mmu_pages, 3);
> +       node->cmdlist.dst_mmu_pages = NULL;
> +}
> +
> +static void rga_cmd_start(struct rockchip_rga *rga,
> +                         struct rga_runqueue_node *runqueue)
> +{
> +       int ret;
> +
> +       ret = pm_runtime_get_sync(rga->dev);
> +       if (ret < 0)
> +               return;
> +
> +       rga_write(rga, RGA_SYS_CTRL, 0x00);
> +
> +       rga_write(rga, RGA_CMD_BASE, runqueue->cmdlist_pool);
> +
> +       rga_write(rga, RGA_SYS_CTRL, 0x22);
> +
> +       rga_write(rga, RGA_INT, 0x600);
> +
> +       rga_write(rga, RGA_CMD_CTRL, ((runqueue->cmdlist_cnt - 1) << 3) | 0x1);
> +}
> +
> +static void rga_free_runqueue_node(struct rockchip_rga *rga,
> +                                  struct rga_runqueue_node *runqueue)
> +{
> +       struct rga_cmdlist_node *node;
> +
> +       if (!runqueue)
> +               return;
> +
> +       if (runqueue->cmdlist_pool_virt && runqueue->cmdlist_pool)
> +               dma_free_attrs(rga->dev, runqueue->cmdlist_cnt * RGA_CMDLIST_SIZE,
> +                              runqueue->cmdlist_pool_virt,
> +                              runqueue->cmdlist_pool,
> +                              &runqueue->cmdlist_dma_attrs);
> +
> +       mutex_lock(&rga->cmdlist_mutex);
> +       /*
> +        * commands in run_cmdlist have been completed so unmap all gem
> +        * objects in each command node so that they are unreferenced.
> +        */
> +       list_for_each_entry(node, &runqueue->run_cmdlist, list)
> +               rga_unmap_cmdlist_gem(rga, node);
> +       list_splice_tail_init(&runqueue->run_cmdlist, &rga->free_cmdlist);
> +       mutex_unlock(&rga->cmdlist_mutex);
> +
> +       kmem_cache_free(rga->runqueue_slab, runqueue);
> +}
> +
> +static struct rga_runqueue_node *rga_get_runqueue(struct rockchip_rga *rga)
> +{
> +       struct rga_runqueue_node *runqueue;
> +
> +       if (list_empty(&rga->runqueue_list))
> +               return NULL;
> +
> +       runqueue = list_first_entry(&rga->runqueue_list,
> +                                   struct rga_runqueue_node, list);
> +       list_del_init(&runqueue->list);
> +
> +       return runqueue;
> +}
> +
> +static void rga_exec_runqueue(struct rockchip_rga *rga)
> +{
> +       rga->runqueue_node = rga_get_runqueue(rga);
> +       if (rga->runqueue_node)
> +               rga_cmd_start(rga, rga->runqueue_node);
> +}
> +
> +static struct rga_cmdlist_node *rga_get_cmdlist(struct rockchip_rga *rga)
> +{
> +       struct rga_cmdlist_node *node;
> +       struct device *dev = rga->dev;
> +
> +       mutex_lock(&rga->cmdlist_mutex);
> +       if (list_empty(&rga->free_cmdlist)) {
> +               dev_err(dev, "there is no free cmdlist\n");
> +               mutex_unlock(&rga->cmdlist_mutex);
> +               return NULL;
> +       }
> +
> +       node = list_first_entry(&rga->free_cmdlist,
> +                               struct rga_cmdlist_node, list);
> +       list_del_init(&node->list);
> +       mutex_unlock(&rga->cmdlist_mutex);
> +
> +       return node;
> +}
> +
> +static void rga_add_cmdlist_to_inuse(struct rockchip_drm_rga_private *rga_priv,
> +                                    struct rga_cmdlist_node *node)
> +{
> +       struct rga_cmdlist_node *lnode;
> +
> +       if (list_empty(&rga_priv->inuse_cmdlist))
> +               goto add_to_list;
> +
> +       /* this links to base address of new cmdlist */
> +       lnode = list_entry(rga_priv->inuse_cmdlist.prev,
> +                          struct rga_cmdlist_node, list);
> +
> +add_to_list:
> +       list_add_tail(&node->list, &rga_priv->inuse_cmdlist);
> +}
> +
> +/*
> + * IOCRL functions for userspace to get RGA version.
> + */
> +int rockchip_rga_get_ver_ioctl(struct drm_device *drm_dev, void *data,
> +                              struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
> +       struct drm_rockchip_rga_get_ver *ver = data;
> +       struct rockchip_rga *rga;
> +       struct device *dev;
> +
> +       if (!rga_priv)
> +               return -ENODEV;
> +
> +       dev = rga_priv->dev;
> +       if (!dev)
> +               return -ENODEV;
> +
> +       rga = dev_get_drvdata(dev);
> +       if (!rga)
> +               return -EFAULT;
> +
> +       ver->major = rga->version.major;
> +       ver->minor = rga->version.minor;
> +
> +       return 0;
> +}
> +
> +/*
> + * IOCRL functions for userspace to send an RGA request.
> + */
> +int rockchip_rga_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
> +                                  struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
> +       struct drm_rockchip_rga_set_cmdlist *req = data;
> +       struct rga_cmdlist_node *node;
> +       struct rga_cmdlist *cmdlist;
> +       struct rockchip_rga *rga;
> +       int ret;
> +
> +       if (!rga_priv)
> +               return -ENODEV;
> +
> +       if (!rga_priv->dev)
> +               return -ENODEV;
> +
> +       rga = dev_get_drvdata(rga_priv->dev);
> +       if (!rga)
> +               return -EFAULT;
> +
> +       node = rga_get_cmdlist(rga);
> +       if (!node)
> +               return -ENOMEM;
> +
> +       cmdlist = &node->cmdlist;
> +       cmdlist->last = 0;
> +
> +       if (req->cmd_nr > RGA_CMDLIST_SIZE || req->cmd_buf_nr > RGA_CMDBUF_SIZE) {
> +               dev_err(rga->dev, "cmdlist size is too big\n");
> +               return -EINVAL;
> +       }
> +
> +       /*
> +        * Copy the command / buffer registers setting from userspace, each
> +        * command have two integer, one for register offset, another for
> +        * register value.
> +        */
> +       if (copy_from_user((void *)cmdlist->data, (const void __user *)req->cmd,
> +                          sizeof(struct drm_rockchip_rga_cmd) * req->cmd_nr))
> +               return -EFAULT;
> +       cmdlist->last += req->cmd_nr * 2;
> +
> +       if (copy_from_user((void *)cmdlist->data + cmdlist->last,
> +                          (const void __user *)req->cmd_buf,
> +                          sizeof(struct drm_rockchip_rga_cmd) * req->cmd_buf_nr))
> +               return -EFAULT;
> +       cmdlist->last += req->cmd_buf_nr * 2;
> +
> +       /*
> +        * Check the userspace command registers, and mapping the framebuffer,
> +        * create the RGA mmu pages or get the framebuffer dma address.
> +        */
> +       ret = rga_check_reg_offset(rga->dev, node);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = rga_map_cmdlist_gem(rga, node, drm_dev, file);
> +       if (ret < 0)
> +               return ret;
> +
> +       rga_add_cmdlist_to_inuse(rga_priv, node);
> +
> +       return 0;
> +}
> +
> +/*
> + * IOCRL functions for userspace to start RGA transform.
> + */
> +int rockchip_rga_exec_ioctl(struct drm_device *drm_dev, void *data,
> +                           struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
> +       struct rga_runqueue_node *runqueue;
> +       struct rockchip_rga *rga;
> +       struct device *dev;
> +       int ret;
> +
> +       if (!rga_priv)
> +               return -ENODEV;
> +
> +       dev = rga_priv->dev;
> +       if (!dev)
> +               return -ENODEV;
> +
> +       rga = dev_get_drvdata(dev);
> +       if (!rga)
> +               return -EFAULT;
> +
> +       runqueue = kmem_cache_alloc(rga->runqueue_slab, GFP_KERNEL);
> +       if (!runqueue) {
> +               dev_err(rga->dev, "failed to allocate memory\n");
> +               return -ENOMEM;
> +       }
> +
> +       runqueue->dev = rga->dev;
> +
> +       init_completion(&runqueue->complete);
> +
> +       INIT_LIST_HEAD(&runqueue->run_cmdlist);
> +
> +       list_splice_init(&rga_priv->inuse_cmdlist, &runqueue->run_cmdlist);
> +
> +       if (list_empty(&runqueue->run_cmdlist)) {
> +               dev_err(rga->dev, "there is no inuse cmdlist\n");
> +               kmem_cache_free(rga->runqueue_slab, runqueue);
> +               return -EPERM;
> +       }
> +
> +       ret = rga_alloc_dma_buf_for_cmdlist(runqueue);
> +       if (ret < 0) {
> +               dev_err(rga->dev, "cmdlist init failed\n");
> +               return ret;
> +       }
> +
> +       mutex_lock(&rga->runqueue_mutex);
> +       runqueue->pid = current->pid;
> +       runqueue->file = file;
> +       list_add_tail(&runqueue->list, &rga->runqueue_list);
> +       if (!rga->runqueue_node)
> +               rga_exec_runqueue(rga);
> +       mutex_unlock(&rga->runqueue_mutex);
> +
> +       wait_for_completion(&runqueue->complete);
> +       rga_free_runqueue_node(rga, runqueue);
> +
> +       return 0;
> +}
> +
> +static int rockchip_rga_open(struct drm_device *drm_dev, struct device *dev,
> +                            struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv;
> +
> +       rga_priv = kzalloc(sizeof(*rga_priv), GFP_KERNEL);
> +       if (!rga_priv)
> +               return -ENOMEM;
> +
> +       rga_priv->dev = dev;
> +       file_priv->rga_priv = rga_priv;
> +
> +       INIT_LIST_HEAD(&rga_priv->inuse_cmdlist);
> +
> +       return 0;
> +}
> +
> +static void rockchip_rga_close(struct drm_device *drm_dev, struct device *dev,
> +                              struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
> +       struct rga_cmdlist_node *node, *n;
> +       struct rockchip_rga *rga;
> +
> +       if (!dev)
> +               return;
> +
> +       rga = dev_get_drvdata(dev);
> +       if (!rga)
> +               return;
> +
> +       mutex_lock(&rga->cmdlist_mutex);
> +       list_for_each_entry_safe(node, n, &rga_priv->inuse_cmdlist, list) {
> +               /*
> +                * unmap all gem objects not completed.
> +                *
> +                * P.S. if current process was terminated forcely then
> +                * there may be some commands in inuse_cmdlist so unmap
> +                * them.
> +                */
> +               rga_unmap_cmdlist_gem(rga, node);
> +               list_move_tail(&node->list, &rga->free_cmdlist);
> +       }
> +       mutex_unlock(&rga->cmdlist_mutex);
> +
> +       kfree(file_priv->rga_priv);
> +}
> +
> +static void rga_runqueue_worker(struct work_struct *work)
> +{
> +       struct rockchip_rga *rga = container_of(work, struct rockchip_rga,
> +                                           runqueue_work);
> +
> +       mutex_lock(&rga->runqueue_mutex);
> +       pm_runtime_put_sync(rga->dev);
> +
> +       complete(&rga->runqueue_node->complete);
> +
> +       if (rga->suspended)
> +               rga->runqueue_node = NULL;
> +       else
> +               rga_exec_runqueue(rga);
> +
> +       mutex_unlock(&rga->runqueue_mutex);
> +}
> +
> +static irqreturn_t rga_irq_handler(int irq, void *dev_id)
> +{
> +       struct rockchip_rga *rga = dev_id;
> +       int intr;
> +
> +       intr = rga_read(rga, RGA_INT) & 0xf;
> +
> +       rga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
> +
> +       if (intr & 0x04)
> +               queue_work(rga->rga_workq, &rga->runqueue_work);
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static int rga_parse_dt(struct rockchip_rga *rga)
> +{
> +       struct reset_control *sclk_rst, *aclk_rst, *hclk_rst;
> +
> +       sclk_rst = devm_reset_control_get(rga->dev, "sclk");
> +       if (IS_ERR(sclk_rst)) {
> +               dev_err(rga->dev, "failed to get sclk reset controller\n");
> +               return PTR_ERR(sclk_rst);
> +       }
> +
> +       aclk_rst = devm_reset_control_get(rga->dev, "aclk");
> +       if (IS_ERR(aclk_rst)) {
> +               dev_err(rga->dev, "failed to get aclk reset controller\n");
> +               return PTR_ERR(aclk_rst);
> +       }
> +
> +       hclk_rst = devm_reset_control_get(rga->dev, "hclk");
> +       if (IS_ERR(hclk_rst)) {
> +               dev_err(rga->dev, "failed to get hclk reset controller\n");
> +               return PTR_ERR(hclk_rst);
> +       }
> +
> +       reset_control_assert(sclk_rst);
> +       usleep_range(10, 20);
> +       reset_control_deassert(sclk_rst);
> +
> +       reset_control_assert(aclk_rst);
> +       usleep_range(10, 20);
> +       reset_control_deassert(aclk_rst);
> +
> +       reset_control_assert(hclk_rst);
> +       usleep_range(10, 20);
> +       reset_control_deassert(hclk_rst);
> +
> +       rga->sclk = devm_clk_get(rga->dev, "sclk");
> +       if (IS_ERR(rga->sclk)) {
> +               dev_err(rga->dev, "failed to get sclk clock\n");
> +               return PTR_ERR(rga->sclk);
> +       }
> +
> +       rga->aclk = devm_clk_get(rga->dev, "aclk");
> +       if (IS_ERR(rga->aclk)) {
> +               dev_err(rga->dev, "failed to get aclk clock\n");
> +               return PTR_ERR(rga->aclk);
> +       }
> +
> +       rga->hclk = devm_clk_get(rga->dev, "hclk");
> +       if (IS_ERR(rga->hclk)) {
> +               dev_err(rga->dev, "failed to get hclk clock\n");
> +               return PTR_ERR(rga->hclk);
> +       }
> +
> +       return rga_enable_clocks(rga);
> +}
> +
> +static const struct of_device_id rockchip_rga_dt_ids[] = {
> +       { .compatible = "rockchip,rk3288-rga", },
> +       { .compatible = "rockchip,rk3228-rga", },
> +       { .compatible = "rockchip,rk3399-rga", },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, rockchip_rga_dt_ids);
> +
> +static int rga_probe(struct platform_device *pdev)
> +{
> +       struct drm_rockchip_subdrv *subdrv;
> +       struct rockchip_rga *rga;
> +       struct resource *iores;
> +       int irq;
> +       int ret;
> +
> +       if (!pdev->dev.of_node)
> +               return -ENODEV;
> +
> +       rga = devm_kzalloc(&pdev->dev, sizeof(*rga), GFP_KERNEL);
> +       if (!rga)
> +               return -ENOMEM;
> +
> +       rga->dev = &pdev->dev;
> +
> +       rga->runqueue_slab = kmem_cache_create("rga_runqueue_slab",
> +                                              sizeof(struct rga_runqueue_node),
> +                                              0, 0, NULL);
> +       if (!rga->runqueue_slab)
> +               return -ENOMEM;
> +
> +       rga->rga_workq = create_singlethread_workqueue("rga");
> +       if (!rga->rga_workq) {
> +               dev_err(rga->dev, "failed to create workqueue\n");
> +               goto err_destroy_slab;
> +       }
> +
> +       INIT_WORK(&rga->runqueue_work, rga_runqueue_worker);
> +       INIT_LIST_HEAD(&rga->runqueue_list);
> +       mutex_init(&rga->runqueue_mutex);
> +
> +       INIT_LIST_HEAD(&rga->free_cmdlist);
> +       mutex_init(&rga->cmdlist_mutex);
> +
> +       rga_init_cmdlist(rga);
> +
> +       ret = rga_parse_dt(rga);
> +       if (ret) {
> +               dev_err(rga->dev, "Unable to parse OF data\n");
> +               goto err_destroy_workqueue;
> +       }
> +
> +       pm_runtime_enable(rga->dev);
> +
> +       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +       rga->regs = devm_ioremap_resource(rga->dev, iores);
> +       if (IS_ERR(rga->regs)) {
> +               ret = PTR_ERR(rga->regs);
> +               goto err_put_clk;
> +       }
> +
> +       irq = platform_get_irq(pdev, 0);
> +       if (irq < 0) {
> +               dev_err(rga->dev, "failed to get irq\n");
> +               ret = irq;
> +               goto err_put_clk;
> +       }
> +
> +       ret = devm_request_irq(rga->dev, irq, rga_irq_handler, 0,
> +                              dev_name(rga->dev), rga);
> +       if (ret < 0) {
> +               dev_err(rga->dev, "failed to request irq\n");
> +               goto err_put_clk;
> +       }
> +
> +       platform_set_drvdata(pdev, rga);
> +
> +       rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
> +       rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
> +
> +       subdrv = &rga->subdrv;
> +       subdrv->dev = rga->dev;
> +       subdrv->open = rockchip_rga_open;
> +       subdrv->close = rockchip_rga_close;
> +
> +       rockchip_register_subdrv(subdrv);
> +
> +       return 0;
> +
> +err_put_clk:
> +       pm_runtime_disable(rga->dev);
> +err_destroy_workqueue:
> +       destroy_workqueue(rga->rga_workq);
> +err_destroy_slab:
> +       kmem_cache_destroy(rga->runqueue_slab);
> +
> +       return ret;
> +}
> +
> +static int rga_remove(struct platform_device *pdev)
> +{
> +       struct rockchip_rga *rga = platform_get_drvdata(pdev);
> +
> +       cancel_work_sync(&rga->runqueue_work);
> +
> +       while (rga->runqueue_node) {
> +               rga_free_runqueue_node(rga, rga->runqueue_node);
> +               rga->runqueue_node = rga_get_runqueue(rga);
> +       }
> +
> +       rockchip_unregister_subdrv(&rga->subdrv);
> +
> +       return 0;
> +}
> +
> +static int rga_suspend(struct device *dev)
> +{
> +       struct rockchip_rga *rga = dev_get_drvdata(dev);
> +
> +       mutex_lock(&rga->runqueue_mutex);
> +       rga->suspended = true;
> +       mutex_unlock(&rga->runqueue_mutex);
> +
> +       flush_work(&rga->runqueue_work);
> +
> +       return 0;
> +}
> +
> +static int rga_resume(struct device *dev)
> +{
> +       struct rockchip_rga *rga = dev_get_drvdata(dev);
> +
> +       rga->suspended = false;
> +       rga_exec_runqueue(rga);
> +
> +       return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int rga_runtime_suspend(struct device *dev)
> +{
> +       struct rockchip_rga *rga = dev_get_drvdata(dev);
> +
> +       rga_disable_clocks(rga);
> +
> +       return 0;
> +}
> +
> +static int rga_runtime_resume(struct device *dev)
> +{
> +       struct rockchip_rga *rga = dev_get_drvdata(dev);
> +
> +       return rga_enable_clocks(rga);
> +}
> +#endif
> +
> +static const struct dev_pm_ops rga_pm = {
> +       SET_SYSTEM_SLEEP_PM_OPS(rga_suspend, rga_resume)
> +       SET_RUNTIME_PM_OPS(rga_runtime_suspend,
> +                          rga_runtime_resume, NULL)
> +};
> +
> +static struct platform_driver rga_pltfm_driver = {
> +       .probe  = rga_probe,
> +       .remove = rga_remove,
> +       .driver = {
> +               .name = "rockchip-rga",
> +               .pm = &rga_pm,
> +               .of_match_table = rockchip_rga_dt_ids,
> +       },
> +};
> +
> +module_platform_driver(rga_pltfm_driver);
> +
> +MODULE_AUTHOR("Yakir Yang <ykk-TNX95d0MmH7DzftRWevZcw@public.gmane.org>");
> +MODULE_DESCRIPTION("Rockchip RGA Driver Extension");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:rockchip-rga");
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_rga.h b/drivers/gpu/drm/rockchip/rockchip_drm_rga.h
> new file mode 100644
> index 0000000..4a8839a
> --- /dev/null
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_rga.h
> @@ -0,0 +1,108 @@
> +#ifndef __ROCKCHIP_DRM_RGA__
> +#define __ROCKCHIP_DRM_RGA__
> +
> +#define RGA_CMDBUF_SIZE                        14
> +#define RGA_CMDLIST_SIZE               0x20
> +#define RGA_CMDLIST_NUM                        64
> +
> +/* cmdlist data structure */
> +struct rga_cmdlist {
> +       u32             head;
> +       unsigned long   data[RGA_CMDLIST_SIZE * 2];
> +       u32             last;   /* last data offset */
> +       void            *src_mmu_pages;
> +       void            *dst_mmu_pages;
> +       void            *src1_mmu_pages;
> +       struct dma_buf_attachment *src_attach;
> +       struct dma_buf_attachment *dst_attach;
> +};
> +
> +struct rga_cmdlist_node {
> +       struct list_head        list;
> +       struct rga_cmdlist      cmdlist;
> +};
> +
> +struct rga_runqueue_node {
> +       struct list_head        list;
> +
> +       struct device           *dev;
> +       pid_t                   pid;
> +       struct drm_file         *file;
> +       struct completion       complete;
> +
> +       struct list_head        run_cmdlist;
> +
> +       int                     cmdlist_cnt;
> +       void                    *cmdlist_pool_virt;
> +       dma_addr_t              cmdlist_pool;
> +       struct dma_attrs        cmdlist_dma_attrs;
> +};
> +
> +struct rockchip_rga_version {
> +       __u32                   major;
> +       __u32                   minor;
> +};
> +
> +struct rockchip_rga {
> +       struct drm_device       *drm_dev;
> +       struct device           *dev;
> +       struct regmap           *grf;
> +       void __iomem            *regs;
> +       struct clk              *sclk;
> +       struct clk              *aclk;
> +       struct clk              *hclk;
> +
> +       bool                            suspended;
> +       struct rockchip_rga_version     version;
> +       struct drm_rockchip_subdrv      subdrv;
> +       struct workqueue_struct         *rga_workq;
> +       struct work_struct              runqueue_work;
> +
> +       /* rga command list pool */
> +       struct rga_cmdlist_node         cmdlist_node[RGA_CMDLIST_NUM];
> +       struct mutex                    cmdlist_mutex;
> +
> +       struct list_head                free_cmdlist;
> +
> +       /* rga runqueue */
> +       struct rga_runqueue_node        *runqueue_node;
> +       struct list_head                runqueue_list;
> +       struct mutex                    runqueue_mutex;
> +       struct kmem_cache               *runqueue_slab;
> +};
> +
> +struct rockchip_drm_rga_private {
> +       struct device           *dev;
> +       struct list_head        inuse_cmdlist;
> +       struct list_head        userptr_list;
> +};
> +
> +#ifdef CONFIG_ROCKCHIP_DRM_RGA
> +int rockchip_rga_get_ver_ioctl(struct drm_device *dev, void *data,
> +                              struct drm_file *file_priv);
> +int rockchip_rga_set_cmdlist_ioctl(struct drm_device *dev, void *data,
> +                                  struct drm_file *file_priv);
> +int rockchip_rga_exec_ioctl(struct drm_device *dev, void *data,
> +                           struct drm_file *file_priv);
> +#else
> +static inline int rockchip_rga_get_ver_ioctl(struct drm_device *dev, void *data,
> +                                            struct drm_file *file_priv)
> +{
> +       return -ENODEV;
> +}
> +
> +static inline int rockchip_rga_set_cmdlist_ioctl(struct drm_device *dev,
> +                                                void *data,
> +                                                struct drm_file *file_priv)
> +{
> +       return -ENODEV;
> +}
> +
> +static inline int rockchip_rga_exec_ioctl(struct drm_device *dev, void *data,
> +                                         struct drm_file *file_priv)
> +{
> +       return -ENODEV;
> +}
> +#endif
> +
> +#endif /* __ROCKCHIP_DRM_RGA__ */
> diff --git a/include/uapi/drm/rockchip_drm.h b/include/uapi/drm/rockchip_drm.h
> new file mode 100644
> index 0000000..2e3e240
> --- /dev/null
> +++ b/include/uapi/drm/rockchip_drm.h
> @@ -0,0 +1,63 @@
> +/* rockchip_drm.h
> + *
> + * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd.
> + * Authors:
> + *     Yakir Yang <ykk-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + */
> +
> +#ifndef _UAPI_ROCKCHIP_DRM_H_
> +#define _UAPI_ROCKCHIP_DRM_H_
> +
> +#include <drm/drm.h>
> +
> +struct drm_rockchip_rga_get_ver {
> +       __u32   major;
> +       __u32   minor;
> +};
> +
> +struct drm_rockchip_rga_cmd {
> +       __u32   offset;
> +       __u32   data;
> +};
> +
> +enum drm_rockchip_rga_buf_type {
> +       RGA_BUF_TYPE_USERPTR = 1 << 31,
> +       RGA_BUF_TYPE_GEMFD   = 1 << 30,
> +};
> +
> +struct drm_rockchip_rga_userptr {
> +       unsigned long userptr;
> +       unsigned long size;
> +};
> +
> +struct drm_rockchip_rga_set_cmdlist {
> +       __u64           cmd;
> +       __u64           cmd_buf;
> +       __u32           cmd_nr;
> +       __u32           cmd_buf_nr;
> +       __u64           user_data;
> +};
> +
> +struct drm_rockchip_rga_exec {
> +       __u64           async;
> +};
> +
> +#define DRM_ROCKCHIP_RGA_GET_VER               0x20
> +#define DRM_ROCKCHIP_RGA_SET_CMDLIST           0x21
> +#define DRM_ROCKCHIP_RGA_EXEC                  0x22
> +
> +#define DRM_IOCTL_ROCKCHIP_RGA_GET_VER         DRM_IOWR(DRM_COMMAND_BASE + \
> +       DRM_ROCKCHIP_RGA_GET_VER, struct drm_rockchip_rga_get_ver)
> +
> +#define DRM_IOCTL_ROCKCHIP_RGA_SET_CMDLIST     DRM_IOWR(DRM_COMMAND_BASE + \
> +       DRM_ROCKCHIP_RGA_SET_CMDLIST, struct drm_rockchip_rga_set_cmdlist)
> +
> +#define DRM_IOCTL_ROCKCHIP_RGA_EXEC            DRM_IOWR(DRM_COMMAND_BASE + \
> +       DRM_ROCKCHIP_RGA_EXEC, struct drm_rockchip_rga_exec)
> +
> +#endif /* _UAPI_ROCKCHIP_DRM_H */
> --
> 1.9.1
>
>
> _______________________________________________
> dri-devel mailing list
> dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 2/4] drm: rockchip: add RGA driver support
@ 2016-03-30 18:34     ` Rob Clark
  0 siblings, 0 replies; 73+ messages in thread
From: Rob Clark @ 2016-03-30 18:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 21, 2016 at 5:40 AM, Yakir Yang <ykk@rock-chips.com> wrote:
> Rockchip RGA is a separate 2D raster graphic acceleration unit. It
> accelerates 2D graphics operations, such as point/line drawing, image
> scaling, rotation, BitBLT, alpha blending and image blur/sharpness.
>
> The RGA driver is based on Exynos G2D driver, it is performed by two
> tasks simply.
> 1. Configures the rendering parameters, such as foreground color and
>    coordinates data by setting the drawing context registers.
> 2. Start the rendering process by calling rga_exec() ioctl.
>
> The RGA supports DMA mode as host interface. User can make command list
> to reduce HOST(ARM) loads. The contents of The command list is setted to
> relevant registers of RGA by DMA.
>
> The command list is composed Header and command sets and Tail.
> - Header: The number of command set(4Bytes)
> - Command set: Register offset(4Bytes) + Register data(4Bytes)
> - Tail: Pointer of base address of the other command list(4Bytes)
>
> By Tail field, the G2D can process many command lists without halt at
> one go.
>
> The G2D has following the rendering pipeline.
>                --->     Color Fill     --->
>                |                          |
> --> DMA (read) ---> Src Bitmap Process ----> Alpha/ROP ---> Format convert ---> DMA (Write)
>                |                          |
>                ---> Dst Bitmap Process --->
>
> And supports various operations from the rendering pipeline.
> - copy
> - fast solid color fill
> - rotation
> - flip
> - 4 operand raster operation(ROP4)
> - alpha blending
> - color key
> - dithering
> - etc
>
> User should make the command list to data and registers needed by
> operation to use. The Rockchip RGA driver only manages the command lists
> received from user. Some registers needs memory base address(physical
> address) of image. User doesn't know its physical address, so fills the
> gem handle of that memory than address to command sets, then RGA driver
> converts it to memory base address.
>
> We adds three ioctls for Rockchip RGA.
>
> - ioctls
> DRM_ROCKCHIP_RGA_GET_VER: get the RGA hardware version
> DRM_ROCKCHIP_RGA_SET_CMDLIST: set the command list from user to driver
> DRM_ROCKCHIP_RGA_EXEC: execute the command lists setted to driver

ok, so from a quick look at this (translation: correct me if I'm
wrong, I may be missunderstanding things)

1) it looks like you have a mmu/iommu (which is good, if hw isn't
getting programmed w/ physical addresses then less likely that
cmdstream validation is needed.. unless the mmu can be reprogrammed
from cmdstream?)

2) it looks like you can queue up work and some sort of "command
processor" processes the queued up packets asynchronously from the
cpu, which is also good.. since it's really easy to make 2d accel
slower than cpu, and you really want userspace to be able to continue
asynchronously from hw building up new cmdstream while hw is chewing
on existing ones..

so, assuming I'm not too far off base with that, I think it is strange
for EXEC ioctl to block until completion.  I suspect instead you want
to return a fence (which for now could just be a pipe specific seqno,
although support for fence fd's would be an obvious future extension),
and have a different ioctl that could block until the fence is
completed[1].  (So perhaps have a look at freedreno and etnaviv UAPI
more than exynos g2d.)

Also, not sure if you could submit multiple different blits in one
go..  in particular w/ switching src/dst/op.  If not, you might want
to be able to submit N cmdbufs in one ioctl.

What I'm getting with in all of this, is if you look at how, for
example, glyph rendering works in x11, there will be a whole lot of
small blit ops each glyph sized.  (So maybe less than 20x20 pixels.)
For that sort of use case you really want to queue up as many as you
can, rather than doing an ioctl call for each.

I think the suggesion on the cover-letter thread about implementing
EXA support for xf86-video-armsoc (or -rockchip if there is such a
thing) is a *really* good idea.  Not just to have a real-world
userspace consumer of the API, but also to help identify all the
things you are going to want to change about the UAPI to get decent
performance ;-)

BR,
-R

[1] see PrepareAccess/FinishAccess hooks in EXA for times when CPU
access to a buffer is needed

> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> ---
>  .../bindings/display/rockchip/rockchip-rga.txt     |  36 +
>  drivers/gpu/drm/rockchip/Kconfig                   |   9 +
>  drivers/gpu/drm/rockchip/Makefile                  |   1 +
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c        |  35 +-
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.h        |   4 +
>  drivers/gpu/drm/rockchip/rockchip_drm_rga.c        | 977 +++++++++++++++++++++
>  drivers/gpu/drm/rockchip/rockchip_drm_rga.h        | 108 +++
>  include/uapi/drm/rockchip_drm.h                    |  63 ++
>  8 files changed, 1232 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
>  create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.c
>  create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_rga.h
>  create mode 100644 include/uapi/drm/rockchip_drm.h
>
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
> new file mode 100644
> index 0000000..0c606cb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-rga.txt
> @@ -0,0 +1,36 @@
> +device-tree bindings for rockchip 2D raster graphic acceleration controller (RGA)
> +
> +RGA is a separate 2D raster graphic acceleration unit. It accelerates 2D
> +graphics operations, such as point/line drawing, image scaling, rotation,
> +BitBLT, alpha blending and image blur/sharpness.
> +
> +Required properties:
> +- compatible: value should be one of the following
> +               "rockchip,rk3228-rga";
> +               "rockchip,rk3288-rga";
> +               "rockchip,rk3399-rga";
> +
> +- interrupts: RGA interrupt number.
> +
> +- clocks: phandle to RGA sclk/hclk/aclk clocks
> +
> +- clock-names: should be "aclk" "hclk" and "sclk"
> +
> +- resets: Must contain an entry for each entry in reset-names.
> +  See ../reset/reset.txt for details.
> +- reset-names: should be "aclk" "hclk" and "sclk"
> +
> +Example:
> +SoC specific DT entry:
> +       rga: rga at ff680000 {
> +               compatible = "rockchip,rk3399-rga";
> +               reg = <0xff680000 0x10000>;
> +               interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
> +               interrupt-names = "rga";
> +               clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>;
> +               clock-names = "aclk", "hclk", "sclk";
> +
> +               resets = <&cru SRST_A_RGA>, <&cru SRST_H_RGA>, <&cru SRST_RGA_CORE>;
> +               reset-names = "aclk", "hclk", "sclk";
> +               status = "disabled";
> +       };
> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> index 76b3362..220221b 100644
> --- a/drivers/gpu/drm/rockchip/Kconfig
> +++ b/drivers/gpu/drm/rockchip/Kconfig
> @@ -16,6 +16,15 @@ config DRM_ROCKCHIP
>           2D or 3D acceleration; acceleration is performed by other
>           IP found on the SoC.
>
> +config ROCKCHIP_DRM_RGA
> +       tristate "Rockchip RGA support"
> +       depends on DRM_ROCKCHIP
> +       help
> +         Choose this option to enable support for Rockchip RGA.
> +         Rockchip RGA is a kind of hardware 2D accelerator, and it support
> +         solid roration, scaling, color format transform, say Y to enable its
> +         driver
> +
>  config ROCKCHIP_DW_HDMI
>          tristate "Rockchip specific extensions for Synopsys DW HDMI"
>          depends on DRM_ROCKCHIP
> diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
> index df8fbef..7de547c 100644
> --- a/drivers/gpu/drm/rockchip/Makefile
> +++ b/drivers/gpu/drm/rockchip/Makefile
> @@ -9,5 +9,6 @@ rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
>  obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
>  obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
>  obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
> +obj-$(CONFIG_ROCKCHIP_DRM_RGA) += rockchip_drm_rga.o
>
>  obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_vop_reg.o
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> index 4e0feb2..1638bc9 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -25,10 +25,13 @@
>  #include <linux/of_graph.h>
>  #include <linux/component.h>
>
> +#include <drm/rockchip_drm.h>
> +
>  #include "rockchip_drm_drv.h"
>  #include "rockchip_drm_fb.h"
>  #include "rockchip_drm_fbdev.h"
>  #include "rockchip_drm_gem.h"
> +#include "rockchip_drm_rga.h"
>
>  #define DRIVER_NAME    "rockchip"
>  #define DRIVER_DESC    "RockChip Soc DRM"
> @@ -277,16 +280,28 @@ EXPORT_SYMBOL_GPL(rockchip_unregister_subdrv);
>
>  static int rockchip_drm_open(struct drm_device *dev, struct drm_file *file)
>  {
> +       struct rockchip_drm_file_private *file_priv;
>         struct drm_rockchip_subdrv *subdrv;
>         int ret = 0;
>
> +       file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
> +       if (!file_priv)
> +               return -ENOMEM;
> +
> +       file->driver_priv = file_priv;
> +
>         list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list) {
>                 ret = subdrv->open(dev, subdrv->dev, file);
>                 if (ret)
> -                       return ret;
> +                       goto err_file_priv_free;
>         }
>
>         return 0;
> +
> +err_file_priv_free:
> +       kfree(file_priv);
> +       file->driver_priv = NULL;
> +       return ret;
>  }
>
>  static void rockchip_drm_preclose(struct drm_device *dev,
> @@ -298,6 +313,12 @@ static void rockchip_drm_preclose(struct drm_device *dev,
>                 subdrv->close(dev, subdrv->dev, file);
>  }
>
> +static void rockchip_drm_postclose(struct drm_device *dev,
> +                                  struct drm_file *file)
> +{
> +       kfree(file->driver_priv);
> +}
> +
>  void rockchip_drm_lastclose(struct drm_device *dev)
>  {
>         struct rockchip_drm_private *priv = dev->dev_private;
> @@ -305,6 +326,15 @@ void rockchip_drm_lastclose(struct drm_device *dev)
>         drm_fb_helper_restore_fbdev_mode_unlocked(&priv->fbdev_helper);
>  }
>
> +static const struct drm_ioctl_desc rockchip_ioctls[] = {
> +       DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_GET_VER, rockchip_rga_get_ver_ioctl,
> +                         DRM_AUTH | DRM_RENDER_ALLOW),
> +       DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_SET_CMDLIST, rockchip_rga_set_cmdlist_ioctl,
> +                         DRM_AUTH | DRM_RENDER_ALLOW),
> +       DRM_IOCTL_DEF_DRV(ROCKCHIP_RGA_EXEC, rockchip_rga_exec_ioctl,
> +                         DRM_AUTH | DRM_RENDER_ALLOW),
> +};
> +
>  static const struct file_operations rockchip_drm_driver_fops = {
>         .owner = THIS_MODULE,
>         .open = drm_open,
> @@ -330,6 +360,7 @@ static struct drm_driver rockchip_drm_driver = {
>         .unload                 = rockchip_drm_unload,
>         .open                   = rockchip_drm_open,
>         .preclose               = rockchip_drm_preclose,
> +       .postclose              = rockchip_drm_postclose,
>         .lastclose              = rockchip_drm_lastclose,
>         .get_vblank_counter     = drm_vblank_no_hw_counter,
>         .enable_vblank          = rockchip_drm_crtc_enable_vblank,
> @@ -347,6 +378,8 @@ static struct drm_driver rockchip_drm_driver = {
>         .gem_prime_vmap         = rockchip_gem_prime_vmap,
>         .gem_prime_vunmap       = rockchip_gem_prime_vunmap,
>         .gem_prime_mmap         = rockchip_gem_mmap_buf,
> +       .ioctls                 = rockchip_ioctls,
> +       .num_ioctls             = ARRAY_SIZE(rockchip_ioctls),
>         .fops                   = &rockchip_drm_driver_fops,
>         .name   = DRIVER_NAME,
>         .desc   = DRIVER_DESC,
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> index 5ea5fcb..ea30ba6 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> @@ -53,6 +53,10 @@ struct drm_rockchip_subdrv {
>                       struct drm_file *file);
>  };
>
> +struct rockchip_drm_file_private {
> +       struct rockchip_drm_rga_private *rga_priv;
> +};
> +
>  struct rockchip_atomic_commit {
>         struct work_struct      work;
>         struct drm_atomic_state *state;
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_rga.c b/drivers/gpu/drm/rockchip/rockchip_drm_rga.c
> new file mode 100644
> index 0000000..4202121
> --- /dev/null
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_rga.c
> @@ -0,0 +1,977 @@
> +/*
> + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
> + * Author: Yakir Yang <ykk@rock-chips.com>
> + *
> + * based on exynos_drm_g2d.c
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/debugfs.h>
> +#include <linux/delay.h>
> +#include <linux/dma-buf.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/interrupt.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/reset.h>
> +#include <linux/seq_file.h>
> +#include <linux/slab.h>
> +#include <linux/uaccess.h>
> +
> +#include <asm/cacheflush.h>
> +#include <drm/drmP.h>
> +#include <drm/rockchip_drm.h>
> +
> +#include "rockchip_drm_drv.h"
> +#include "rockchip_drm_rga.h"
> +
> +#define RGA_MODE_BASE_REG              0x0100
> +#define RGA_MODE_MAX_REG               0x017C
> +
> +#define RGA_SYS_CTRL                   0x0000
> +#define RGA_CMD_CTRL                   0x0004
> +#define RGA_CMD_BASE                   0x0008
> +#define RGA_INT                                0x0010
> +#define RGA_MMU_CTRL0                  0x0014
> +#define RGA_VERSION_INFO               0x0028
> +
> +#define RGA_SRC_Y_RGB_BASE_ADDR                0x0108
> +#define RGA_SRC_CB_BASE_ADDR           0x010C
> +#define RGA_SRC_CR_BASE_ADDR           0x0110
> +#define RGA_SRC1_RGB_BASE_ADDR         0x0114
> +#define RGA_DST_Y_RGB_BASE_ADDR                0x013C
> +#define RGA_DST_CB_BASE_ADDR           0x0140
> +#define RGA_DST_CR_BASE_ADDR           0x014C
> +#define RGA_MMU_CTRL1                  0x016C
> +#define RGA_MMU_SRC_BASE               0x0170
> +#define RGA_MMU_SRC1_BASE              0x0174
> +#define RGA_MMU_DST_BASE               0x0178
> +
> +static void rga_dma_flush_range(void *ptr, int size)
> +{
> +#ifdef CONFIG_ARM
> +       dmac_flush_range(ptr, ptr + size);
> +       outer_flush_range(virt_to_phys(ptr), virt_to_phys(ptr + size));
> +#elif CONFIG_ARM64
> +       __dma_flush_range(ptr, ptr + size);
> +#endif
> +}
> +
> +static inline void rga_write(struct rockchip_rga *rga, u32 reg, u32 value)
> +{
> +       writel(value, rga->regs + reg);
> +}
> +
> +static inline u32 rga_read(struct rockchip_rga *rga, u32 reg)
> +{
> +       return readl(rga->regs + reg);
> +}
> +
> +static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
> +{
> +       u32 temp = rga_read(rga, reg) & ~(mask);
> +
> +       temp |= val & mask;
> +       rga_write(rga, reg, temp);
> +}
> +
> +static int rga_enable_clocks(struct rockchip_rga *rga)
> +{
> +       int ret;
> +
> +       ret = clk_prepare_enable(rga->sclk);
> +       if (ret) {
> +               dev_err(rga->dev, "Cannot enable rga sclk: %d\n", ret);
> +               return ret;
> +       }
> +
> +       ret = clk_prepare_enable(rga->aclk);
> +       if (ret) {
> +               dev_err(rga->dev, "Cannot enable rga aclk: %d\n", ret);
> +               goto err_disable_sclk;
> +       }
> +
> +       ret = clk_prepare_enable(rga->hclk);
> +       if (ret) {
> +               dev_err(rga->dev, "Cannot enable rga hclk: %d\n", ret);
> +               goto err_disable_aclk;
> +       }
> +
> +       return 0;
> +
> +err_disable_sclk:
> +       clk_disable_unprepare(rga->sclk);
> +err_disable_aclk:
> +       clk_disable_unprepare(rga->aclk);
> +
> +       return ret;
> +}
> +
> +static void rga_disable_clocks(struct rockchip_rga *rga)
> +{
> +       clk_disable_unprepare(rga->sclk);
> +       clk_disable_unprepare(rga->hclk);
> +       clk_disable_unprepare(rga->aclk);
> +}
> +
> +static void rga_init_cmdlist(struct rockchip_rga *rga)
> +{
> +       struct rga_cmdlist_node *node;
> +       int nr;
> +
> +       node = rga->cmdlist_node;
> +
> +       for (nr = 0; nr < ARRAY_SIZE(rga->cmdlist_node); nr++)
> +               list_add_tail(&node[nr].list, &rga->free_cmdlist);
> +}
> +
> +static int rga_alloc_dma_buf_for_cmdlist(struct rga_runqueue_node *runqueue)
> +{
> +       struct list_head *run_cmdlist = &runqueue->run_cmdlist;
> +       struct device *dev = runqueue->dev;
> +       struct dma_attrs cmdlist_dma_attrs;
> +       struct rga_cmdlist_node *node;
> +       void *cmdlist_pool_virt;
> +       dma_addr_t cmdlist_pool;
> +       int cmdlist_cnt = 0;
> +       int count = 0;
> +
> +       list_for_each_entry(node, run_cmdlist, list)
> +               cmdlist_cnt++;
> +
> +       init_dma_attrs(&cmdlist_dma_attrs);
> +       dma_set_attr(DMA_ATTR_WRITE_COMBINE, &runqueue->cmdlist_dma_attrs);
> +
> +       cmdlist_pool_virt = dma_alloc_attrs(dev, cmdlist_cnt * RGA_CMDLIST_SIZE,
> +                                           &cmdlist_pool, GFP_KERNEL,
> +                                           &cmdlist_dma_attrs);
> +       if (!cmdlist_pool_virt) {
> +               dev_err(dev, "failed to allocate cmdlist dma memory\n");
> +               return -ENOMEM;
> +       }
> +
> +       /*
> +        * Fill in the RGA operation registers from cmdlist command buffer,
> +        * and also filled in the MMU TLB base information.
> +        */
> +       list_for_each_entry(node, run_cmdlist, list) {
> +               struct rga_cmdlist *cmdlist = &node->cmdlist;
> +               unsigned int mmu_ctrl = 0;
> +               unsigned int *dest;
> +               unsigned int reg;
> +               int i;
> +
> +               dest = cmdlist_pool_virt + RGA_CMDLIST_SIZE * 4 * count++;
> +
> +               for (i = 0; i < cmdlist->last / 2; i++) {
> +                       reg = (node->cmdlist.data[2 * i] - RGA_MODE_BASE_REG);
> +                       if (reg > RGA_MODE_BASE_REG)
> +                               continue;
> +                       dest[reg << 2] = cmdlist->data[2 * i + 1];
> +               }
> +
> +               if (cmdlist->src_mmu_pages) {
> +                       reg = RGA_MMU_SRC_BASE - RGA_MODE_BASE_REG;
> +                       dest[reg << 2] = virt_to_phys(cmdlist->src_mmu_pages) >> 4;
> +                       mmu_ctrl |= 0x7;
> +               }
> +
> +               if (cmdlist->dst_mmu_pages) {
> +                       reg = RGA_MMU_DST_BASE - RGA_MODE_BASE_REG;
> +                       dest[reg << 2] = virt_to_phys(cmdlist->dst_mmu_pages) >> 4;
> +                       mmu_ctrl |= 0x7 << 8;
> +               }
> +
> +               if (cmdlist->src1_mmu_pages) {
> +                       reg = RGA_MMU_SRC1_BASE - RGA_MODE_BASE_REG;
> +                       dest[reg << 2] = virt_to_phys(cmdlist->src1_mmu_pages) >> 4;
> +                       mmu_ctrl |= 0x7 << 4;
> +               }
> +
> +               reg = RGA_MMU_CTRL1 - RGA_MODE_BASE_REG;
> +               dest[reg << 2] = mmu_ctrl;
> +       }
> +
> +       rga_dma_flush_range(cmdlist_pool_virt, cmdlist_cnt * RGA_CMDLIST_SIZE);
> +
> +       runqueue->cmdlist_dma_attrs = cmdlist_dma_attrs;
> +       runqueue->cmdlist_pool_virt = cmdlist_pool_virt;
> +       runqueue->cmdlist_pool = cmdlist_pool;
> +       runqueue->cmdlist_cnt = cmdlist_cnt;
> +
> +       return 0;
> +}
> +
> +static int rga_check_reg_offset(struct device *dev,
> +                               struct rga_cmdlist_node *node)
> +{
> +       struct rga_cmdlist *cmdlist = &node->cmdlist;
> +       int index;
> +       int reg;
> +       int i;
> +
> +       for (i = 0; i < cmdlist->last / 2; i++) {
> +               index = cmdlist->last - 2 * (i + 1);
> +               reg = cmdlist->data[index];
> +
> +               switch (reg) {
> +               case RGA_BUF_TYPE_GEMFD | RGA_DST_Y_RGB_BASE_ADDR:
> +               case RGA_BUF_TYPE_GEMFD | RGA_SRC_Y_RGB_BASE_ADDR:
> +                       break;
> +
> +               case RGA_BUF_TYPE_USERPTR | RGA_DST_Y_RGB_BASE_ADDR:
> +               case RGA_BUF_TYPE_USERPTR | RGA_SRC_Y_RGB_BASE_ADDR:
> +                       goto err;
> +
> +               default:
> +                       if (reg < RGA_MODE_BASE_REG || reg > RGA_MODE_MAX_REG)
> +                               goto err;
> +
> +                       if (reg % 4)
> +                               goto err;
> +               }
> +       }
> +
> +       return 0;
> +
> +err:
> +       dev_err(dev, "Bad register offset: 0x%lx\n", cmdlist->data[index]);
> +       return -EINVAL;
> +}
> +
> +static struct dma_buf_attachment *
> +rga_gem_buf_to_pages(struct rockchip_rga *rga, void **mmu_pages, int fd)
> +{
> +       struct dma_buf_attachment *attach;
> +       struct dma_buf *dmabuf;
> +       struct sg_table *sgt;
> +       struct scatterlist *sgl;
> +       unsigned int mapped_size = 0;
> +       unsigned int address;
> +       unsigned int len;
> +       unsigned int i, p;
> +       unsigned int *pages;
> +       int ret;
> +
> +       dmabuf = dma_buf_get(fd);
> +       if (IS_ERR(dmabuf)) {
> +               dev_err(rga->dev, "Failed to get dma_buf with fd %d\n", fd);
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       attach = dma_buf_attach(dmabuf, rga->dev);
> +       if (IS_ERR(attach)) {
> +               dev_err(rga->dev, "Failed to attach dma_buf\n");
> +               ret = PTR_ERR(attach);
> +               goto failed_attach;
> +       }
> +
> +       sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
> +       if (IS_ERR(sgt)) {
> +               dev_err(rga->dev, "Failed to map dma_buf attachment\n");
> +               ret = PTR_ERR(sgt);
> +               goto failed_detach;
> +       }
> +
> +       /*
> +        * Alloc (2^3 * 4K) = 32K byte for storing pages, those space could
> +        * cover 32K * 4K = 128M ram address.
> +        */
> +       pages = (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
> +
> +       for_each_sg(sgt->sgl, sgl, sgt->nents, i) {
> +               len = sg_dma_len(sgl) >> PAGE_SHIFT;
> +               address = sg_phys(sgl);
> +
> +               for (p = 0; p < len; p++) {
> +                       dma_addr_t phys = address + (p << PAGE_SHIFT);
> +                       void *virt = phys_to_virt(phys);
> +
> +                       rga_dma_flush_range(virt, 4 * 1024);
> +                       pages[mapped_size + p] = phys;
> +               }
> +
> +               mapped_size += len;
> +       }
> +
> +       rga_dma_flush_range(pages, 32 * 1024);
> +
> +       *mmu_pages = pages;
> +
> +       dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
> +
> +       return attach;
> +
> +failed_detach:
> +       dma_buf_detach(dmabuf, attach);
> +failed_attach:
> +       dma_buf_put(dmabuf);
> +
> +       return ERR_PTR(ret);
> +}
> +
> +static int rga_map_cmdlist_gem(struct rockchip_rga *rga,
> +                              struct rga_cmdlist_node *node,
> +                              struct drm_device *drm_dev,
> +                              struct drm_file *file)
> +{
> +       struct rga_cmdlist *cmdlist = &node->cmdlist;
> +       struct dma_buf_attachment *attach;
> +       void *mmu_pages;
> +       int fd;
> +       int i;
> +
> +       for (i = 0; i < cmdlist->last / 2; i++) {
> +               int index = cmdlist->last - 2 * (i + 1);
> +
> +               switch (cmdlist->data[index]) {
> +               case RGA_SRC_Y_RGB_BASE_ADDR | RGA_BUF_TYPE_GEMFD:
> +                       fd = cmdlist->data[index + 1];
> +                       attach = rga_gem_buf_to_pages(rga, &mmu_pages, fd);
> +
> +                       cmdlist->src_attach = attach;
> +                       cmdlist->src_mmu_pages = mmu_pages;
> +                       break;
> +
> +               case RGA_DST_Y_RGB_BASE_ADDR | RGA_BUF_TYPE_GEMFD:
> +                       fd = cmdlist->data[index + 1];
> +                       attach = rga_gem_buf_to_pages(rga, &mmu_pages, fd);
> +
> +                       cmdlist->dst_attach = attach;
> +                       cmdlist->dst_mmu_pages = mmu_pages;
> +                       break;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static void rga_unmap_cmdlist_gem(struct rockchip_rga *rga,
> +                                 struct rga_cmdlist_node *node)
> +{
> +       struct dma_buf_attachment *attach;
> +       struct dma_buf *dma_buf;
> +
> +       attach = node->cmdlist.src_attach;
> +       if (attach) {
> +               dma_buf = attach->dmabuf;
> +               dma_buf_detach(dma_buf, attach);
> +               dma_buf_put(dma_buf);
> +       }
> +       node->cmdlist.src_attach = NULL;
> +
> +       attach = node->cmdlist.dst_attach;
> +       if (attach) {
> +               dma_buf = attach->dmabuf;
> +               dma_buf_detach(dma_buf, attach);
> +               dma_buf_put(dma_buf);
> +       }
> +       node->cmdlist.dst_attach = NULL;
> +
> +       if (node->cmdlist.src_mmu_pages)
> +               free_pages((unsigned long)node->cmdlist.src_mmu_pages, 3);
> +       node->cmdlist.src_mmu_pages = NULL;
> +
> +       if (node->cmdlist.src1_mmu_pages)
> +               free_pages((unsigned long)node->cmdlist.src1_mmu_pages, 3);
> +       node->cmdlist.src1_mmu_pages = NULL;
> +
> +       if (node->cmdlist.dst_mmu_pages)
> +               free_pages((unsigned long)node->cmdlist.dst_mmu_pages, 3);
> +       node->cmdlist.dst_mmu_pages = NULL;
> +}
> +
> +static void rga_cmd_start(struct rockchip_rga *rga,
> +                         struct rga_runqueue_node *runqueue)
> +{
> +       int ret;
> +
> +       ret = pm_runtime_get_sync(rga->dev);
> +       if (ret < 0)
> +               return;
> +
> +       rga_write(rga, RGA_SYS_CTRL, 0x00);
> +
> +       rga_write(rga, RGA_CMD_BASE, runqueue->cmdlist_pool);
> +
> +       rga_write(rga, RGA_SYS_CTRL, 0x22);
> +
> +       rga_write(rga, RGA_INT, 0x600);
> +
> +       rga_write(rga, RGA_CMD_CTRL, ((runqueue->cmdlist_cnt - 1) << 3) | 0x1);
> +}
> +
> +static void rga_free_runqueue_node(struct rockchip_rga *rga,
> +                                  struct rga_runqueue_node *runqueue)
> +{
> +       struct rga_cmdlist_node *node;
> +
> +       if (!runqueue)
> +               return;
> +
> +       if (runqueue->cmdlist_pool_virt && runqueue->cmdlist_pool)
> +               dma_free_attrs(rga->dev, runqueue->cmdlist_cnt * RGA_CMDLIST_SIZE,
> +                              runqueue->cmdlist_pool_virt,
> +                              runqueue->cmdlist_pool,
> +                              &runqueue->cmdlist_dma_attrs);
> +
> +       mutex_lock(&rga->cmdlist_mutex);
> +       /*
> +        * commands in run_cmdlist have been completed so unmap all gem
> +        * objects in each command node so that they are unreferenced.
> +        */
> +       list_for_each_entry(node, &runqueue->run_cmdlist, list)
> +               rga_unmap_cmdlist_gem(rga, node);
> +       list_splice_tail_init(&runqueue->run_cmdlist, &rga->free_cmdlist);
> +       mutex_unlock(&rga->cmdlist_mutex);
> +
> +       kmem_cache_free(rga->runqueue_slab, runqueue);
> +}
> +
> +static struct rga_runqueue_node *rga_get_runqueue(struct rockchip_rga *rga)
> +{
> +       struct rga_runqueue_node *runqueue;
> +
> +       if (list_empty(&rga->runqueue_list))
> +               return NULL;
> +
> +       runqueue = list_first_entry(&rga->runqueue_list,
> +                                   struct rga_runqueue_node, list);
> +       list_del_init(&runqueue->list);
> +
> +       return runqueue;
> +}
> +
> +static void rga_exec_runqueue(struct rockchip_rga *rga)
> +{
> +       rga->runqueue_node = rga_get_runqueue(rga);
> +       if (rga->runqueue_node)
> +               rga_cmd_start(rga, rga->runqueue_node);
> +}
> +
> +static struct rga_cmdlist_node *rga_get_cmdlist(struct rockchip_rga *rga)
> +{
> +       struct rga_cmdlist_node *node;
> +       struct device *dev = rga->dev;
> +
> +       mutex_lock(&rga->cmdlist_mutex);
> +       if (list_empty(&rga->free_cmdlist)) {
> +               dev_err(dev, "there is no free cmdlist\n");
> +               mutex_unlock(&rga->cmdlist_mutex);
> +               return NULL;
> +       }
> +
> +       node = list_first_entry(&rga->free_cmdlist,
> +                               struct rga_cmdlist_node, list);
> +       list_del_init(&node->list);
> +       mutex_unlock(&rga->cmdlist_mutex);
> +
> +       return node;
> +}
> +
> +static void rga_add_cmdlist_to_inuse(struct rockchip_drm_rga_private *rga_priv,
> +                                    struct rga_cmdlist_node *node)
> +{
> +       struct rga_cmdlist_node *lnode;
> +
> +       if (list_empty(&rga_priv->inuse_cmdlist))
> +               goto add_to_list;
> +
> +       /* this links to base address of new cmdlist */
> +       lnode = list_entry(rga_priv->inuse_cmdlist.prev,
> +                          struct rga_cmdlist_node, list);
> +
> +add_to_list:
> +       list_add_tail(&node->list, &rga_priv->inuse_cmdlist);
> +}
> +
> +/*
> + * IOCRL functions for userspace to get RGA version.
> + */
> +int rockchip_rga_get_ver_ioctl(struct drm_device *drm_dev, void *data,
> +                              struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
> +       struct drm_rockchip_rga_get_ver *ver = data;
> +       struct rockchip_rga *rga;
> +       struct device *dev;
> +
> +       if (!rga_priv)
> +               return -ENODEV;
> +
> +       dev = rga_priv->dev;
> +       if (!dev)
> +               return -ENODEV;
> +
> +       rga = dev_get_drvdata(dev);
> +       if (!rga)
> +               return -EFAULT;
> +
> +       ver->major = rga->version.major;
> +       ver->minor = rga->version.minor;
> +
> +       return 0;
> +}
> +
> +/*
> + * IOCRL functions for userspace to send an RGA request.
> + */
> +int rockchip_rga_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
> +                                  struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
> +       struct drm_rockchip_rga_set_cmdlist *req = data;
> +       struct rga_cmdlist_node *node;
> +       struct rga_cmdlist *cmdlist;
> +       struct rockchip_rga *rga;
> +       int ret;
> +
> +       if (!rga_priv)
> +               return -ENODEV;
> +
> +       if (!rga_priv->dev)
> +               return -ENODEV;
> +
> +       rga = dev_get_drvdata(rga_priv->dev);
> +       if (!rga)
> +               return -EFAULT;
> +
> +       node = rga_get_cmdlist(rga);
> +       if (!node)
> +               return -ENOMEM;
> +
> +       cmdlist = &node->cmdlist;
> +       cmdlist->last = 0;
> +
> +       if (req->cmd_nr > RGA_CMDLIST_SIZE || req->cmd_buf_nr > RGA_CMDBUF_SIZE) {
> +               dev_err(rga->dev, "cmdlist size is too big\n");
> +               return -EINVAL;
> +       }
> +
> +       /*
> +        * Copy the command / buffer registers setting from userspace, each
> +        * command have two integer, one for register offset, another for
> +        * register value.
> +        */
> +       if (copy_from_user((void *)cmdlist->data, (const void __user *)req->cmd,
> +                          sizeof(struct drm_rockchip_rga_cmd) * req->cmd_nr))
> +               return -EFAULT;
> +       cmdlist->last += req->cmd_nr * 2;
> +
> +       if (copy_from_user((void *)cmdlist->data + cmdlist->last,
> +                          (const void __user *)req->cmd_buf,
> +                          sizeof(struct drm_rockchip_rga_cmd) * req->cmd_buf_nr))
> +               return -EFAULT;
> +       cmdlist->last += req->cmd_buf_nr * 2;
> +
> +       /*
> +        * Check the userspace command registers, and mapping the framebuffer,
> +        * create the RGA mmu pages or get the framebuffer dma address.
> +        */
> +       ret = rga_check_reg_offset(rga->dev, node);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = rga_map_cmdlist_gem(rga, node, drm_dev, file);
> +       if (ret < 0)
> +               return ret;
> +
> +       rga_add_cmdlist_to_inuse(rga_priv, node);
> +
> +       return 0;
> +}
> +
> +/*
> + * IOCRL functions for userspace to start RGA transform.
> + */
> +int rockchip_rga_exec_ioctl(struct drm_device *drm_dev, void *data,
> +                           struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
> +       struct rga_runqueue_node *runqueue;
> +       struct rockchip_rga *rga;
> +       struct device *dev;
> +       int ret;
> +
> +       if (!rga_priv)
> +               return -ENODEV;
> +
> +       dev = rga_priv->dev;
> +       if (!dev)
> +               return -ENODEV;
> +
> +       rga = dev_get_drvdata(dev);
> +       if (!rga)
> +               return -EFAULT;
> +
> +       runqueue = kmem_cache_alloc(rga->runqueue_slab, GFP_KERNEL);
> +       if (!runqueue) {
> +               dev_err(rga->dev, "failed to allocate memory\n");
> +               return -ENOMEM;
> +       }
> +
> +       runqueue->dev = rga->dev;
> +
> +       init_completion(&runqueue->complete);
> +
> +       INIT_LIST_HEAD(&runqueue->run_cmdlist);
> +
> +       list_splice_init(&rga_priv->inuse_cmdlist, &runqueue->run_cmdlist);
> +
> +       if (list_empty(&runqueue->run_cmdlist)) {
> +               dev_err(rga->dev, "there is no inuse cmdlist\n");
> +               kmem_cache_free(rga->runqueue_slab, runqueue);
> +               return -EPERM;
> +       }
> +
> +       ret = rga_alloc_dma_buf_for_cmdlist(runqueue);
> +       if (ret < 0) {
> +               dev_err(rga->dev, "cmdlist init failed\n");
> +               return ret;
> +       }
> +
> +       mutex_lock(&rga->runqueue_mutex);
> +       runqueue->pid = current->pid;
> +       runqueue->file = file;
> +       list_add_tail(&runqueue->list, &rga->runqueue_list);
> +       if (!rga->runqueue_node)
> +               rga_exec_runqueue(rga);
> +       mutex_unlock(&rga->runqueue_mutex);
> +
> +       wait_for_completion(&runqueue->complete);
> +       rga_free_runqueue_node(rga, runqueue);
> +
> +       return 0;
> +}
> +
> +static int rockchip_rga_open(struct drm_device *drm_dev, struct device *dev,
> +                            struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv;
> +
> +       rga_priv = kzalloc(sizeof(*rga_priv), GFP_KERNEL);
> +       if (!rga_priv)
> +               return -ENOMEM;
> +
> +       rga_priv->dev = dev;
> +       file_priv->rga_priv = rga_priv;
> +
> +       INIT_LIST_HEAD(&rga_priv->inuse_cmdlist);
> +
> +       return 0;
> +}
> +
> +static void rockchip_rga_close(struct drm_device *drm_dev, struct device *dev,
> +                              struct drm_file *file)
> +{
> +       struct rockchip_drm_file_private *file_priv = file->driver_priv;
> +       struct rockchip_drm_rga_private *rga_priv = file_priv->rga_priv;
> +       struct rga_cmdlist_node *node, *n;
> +       struct rockchip_rga *rga;
> +
> +       if (!dev)
> +               return;
> +
> +       rga = dev_get_drvdata(dev);
> +       if (!rga)
> +               return;
> +
> +       mutex_lock(&rga->cmdlist_mutex);
> +       list_for_each_entry_safe(node, n, &rga_priv->inuse_cmdlist, list) {
> +               /*
> +                * unmap all gem objects not completed.
> +                *
> +                * P.S. if current process was terminated forcely then
> +                * there may be some commands in inuse_cmdlist so unmap
> +                * them.
> +                */
> +               rga_unmap_cmdlist_gem(rga, node);
> +               list_move_tail(&node->list, &rga->free_cmdlist);
> +       }
> +       mutex_unlock(&rga->cmdlist_mutex);
> +
> +       kfree(file_priv->rga_priv);
> +}
> +
> +static void rga_runqueue_worker(struct work_struct *work)
> +{
> +       struct rockchip_rga *rga = container_of(work, struct rockchip_rga,
> +                                           runqueue_work);
> +
> +       mutex_lock(&rga->runqueue_mutex);
> +       pm_runtime_put_sync(rga->dev);
> +
> +       complete(&rga->runqueue_node->complete);
> +
> +       if (rga->suspended)
> +               rga->runqueue_node = NULL;
> +       else
> +               rga_exec_runqueue(rga);
> +
> +       mutex_unlock(&rga->runqueue_mutex);
> +}
> +
> +static irqreturn_t rga_irq_handler(int irq, void *dev_id)
> +{
> +       struct rockchip_rga *rga = dev_id;
> +       int intr;
> +
> +       intr = rga_read(rga, RGA_INT) & 0xf;
> +
> +       rga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
> +
> +       if (intr & 0x04)
> +               queue_work(rga->rga_workq, &rga->runqueue_work);
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static int rga_parse_dt(struct rockchip_rga *rga)
> +{
> +       struct reset_control *sclk_rst, *aclk_rst, *hclk_rst;
> +
> +       sclk_rst = devm_reset_control_get(rga->dev, "sclk");
> +       if (IS_ERR(sclk_rst)) {
> +               dev_err(rga->dev, "failed to get sclk reset controller\n");
> +               return PTR_ERR(sclk_rst);
> +       }
> +
> +       aclk_rst = devm_reset_control_get(rga->dev, "aclk");
> +       if (IS_ERR(aclk_rst)) {
> +               dev_err(rga->dev, "failed to get aclk reset controller\n");
> +               return PTR_ERR(aclk_rst);
> +       }
> +
> +       hclk_rst = devm_reset_control_get(rga->dev, "hclk");
> +       if (IS_ERR(hclk_rst)) {
> +               dev_err(rga->dev, "failed to get hclk reset controller\n");
> +               return PTR_ERR(hclk_rst);
> +       }
> +
> +       reset_control_assert(sclk_rst);
> +       usleep_range(10, 20);
> +       reset_control_deassert(sclk_rst);
> +
> +       reset_control_assert(aclk_rst);
> +       usleep_range(10, 20);
> +       reset_control_deassert(aclk_rst);
> +
> +       reset_control_assert(hclk_rst);
> +       usleep_range(10, 20);
> +       reset_control_deassert(hclk_rst);
> +
> +       rga->sclk = devm_clk_get(rga->dev, "sclk");
> +       if (IS_ERR(rga->sclk)) {
> +               dev_err(rga->dev, "failed to get sclk clock\n");
> +               return PTR_ERR(rga->sclk);
> +       }
> +
> +       rga->aclk = devm_clk_get(rga->dev, "aclk");
> +       if (IS_ERR(rga->aclk)) {
> +               dev_err(rga->dev, "failed to get aclk clock\n");
> +               return PTR_ERR(rga->aclk);
> +       }
> +
> +       rga->hclk = devm_clk_get(rga->dev, "hclk");
> +       if (IS_ERR(rga->hclk)) {
> +               dev_err(rga->dev, "failed to get hclk clock\n");
> +               return PTR_ERR(rga->hclk);
> +       }
> +
> +       return rga_enable_clocks(rga);
> +}
> +
> +static const struct of_device_id rockchip_rga_dt_ids[] = {
> +       { .compatible = "rockchip,rk3288-rga", },
> +       { .compatible = "rockchip,rk3228-rga", },
> +       { .compatible = "rockchip,rk3399-rga", },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, rockchip_rga_dt_ids);
> +
> +static int rga_probe(struct platform_device *pdev)
> +{
> +       struct drm_rockchip_subdrv *subdrv;
> +       struct rockchip_rga *rga;
> +       struct resource *iores;
> +       int irq;
> +       int ret;
> +
> +       if (!pdev->dev.of_node)
> +               return -ENODEV;
> +
> +       rga = devm_kzalloc(&pdev->dev, sizeof(*rga), GFP_KERNEL);
> +       if (!rga)
> +               return -ENOMEM;
> +
> +       rga->dev = &pdev->dev;
> +
> +       rga->runqueue_slab = kmem_cache_create("rga_runqueue_slab",
> +                                              sizeof(struct rga_runqueue_node),
> +                                              0, 0, NULL);
> +       if (!rga->runqueue_slab)
> +               return -ENOMEM;
> +
> +       rga->rga_workq = create_singlethread_workqueue("rga");
> +       if (!rga->rga_workq) {
> +               dev_err(rga->dev, "failed to create workqueue\n");
> +               goto err_destroy_slab;
> +       }
> +
> +       INIT_WORK(&rga->runqueue_work, rga_runqueue_worker);
> +       INIT_LIST_HEAD(&rga->runqueue_list);
> +       mutex_init(&rga->runqueue_mutex);
> +
> +       INIT_LIST_HEAD(&rga->free_cmdlist);
> +       mutex_init(&rga->cmdlist_mutex);
> +
> +       rga_init_cmdlist(rga);
> +
> +       ret = rga_parse_dt(rga);
> +       if (ret) {
> +               dev_err(rga->dev, "Unable to parse OF data\n");
> +               goto err_destroy_workqueue;
> +       }
> +
> +       pm_runtime_enable(rga->dev);
> +
> +       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +       rga->regs = devm_ioremap_resource(rga->dev, iores);
> +       if (IS_ERR(rga->regs)) {
> +               ret = PTR_ERR(rga->regs);
> +               goto err_put_clk;
> +       }
> +
> +       irq = platform_get_irq(pdev, 0);
> +       if (irq < 0) {
> +               dev_err(rga->dev, "failed to get irq\n");
> +               ret = irq;
> +               goto err_put_clk;
> +       }
> +
> +       ret = devm_request_irq(rga->dev, irq, rga_irq_handler, 0,
> +                              dev_name(rga->dev), rga);
> +       if (ret < 0) {
> +               dev_err(rga->dev, "failed to request irq\n");
> +               goto err_put_clk;
> +       }
> +
> +       platform_set_drvdata(pdev, rga);
> +
> +       rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
> +       rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
> +
> +       subdrv = &rga->subdrv;
> +       subdrv->dev = rga->dev;
> +       subdrv->open = rockchip_rga_open;
> +       subdrv->close = rockchip_rga_close;
> +
> +       rockchip_register_subdrv(subdrv);
> +
> +       return 0;
> +
> +err_put_clk:
> +       pm_runtime_disable(rga->dev);
> +err_destroy_workqueue:
> +       destroy_workqueue(rga->rga_workq);
> +err_destroy_slab:
> +       kmem_cache_destroy(rga->runqueue_slab);
> +
> +       return ret;
> +}
> +
> +static int rga_remove(struct platform_device *pdev)
> +{
> +       struct rockchip_rga *rga = platform_get_drvdata(pdev);
> +
> +       cancel_work_sync(&rga->runqueue_work);
> +
> +       while (rga->runqueue_node) {
> +               rga_free_runqueue_node(rga, rga->runqueue_node);
> +               rga->runqueue_node = rga_get_runqueue(rga);
> +       }
> +
> +       rockchip_unregister_subdrv(&rga->subdrv);
> +
> +       return 0;
> +}
> +
> +static int rga_suspend(struct device *dev)
> +{
> +       struct rockchip_rga *rga = dev_get_drvdata(dev);
> +
> +       mutex_lock(&rga->runqueue_mutex);
> +       rga->suspended = true;
> +       mutex_unlock(&rga->runqueue_mutex);
> +
> +       flush_work(&rga->runqueue_work);
> +
> +       return 0;
> +}
> +
> +static int rga_resume(struct device *dev)
> +{
> +       struct rockchip_rga *rga = dev_get_drvdata(dev);
> +
> +       rga->suspended = false;
> +       rga_exec_runqueue(rga);
> +
> +       return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int rga_runtime_suspend(struct device *dev)
> +{
> +       struct rockchip_rga *rga = dev_get_drvdata(dev);
> +
> +       rga_disable_clocks(rga);
> +
> +       return 0;
> +}
> +
> +static int rga_runtime_resume(struct device *dev)
> +{
> +       struct rockchip_rga *rga = dev_get_drvdata(dev);
> +
> +       return rga_enable_clocks(rga);
> +}
> +#endif
> +
> +static const struct dev_pm_ops rga_pm = {
> +       SET_SYSTEM_SLEEP_PM_OPS(rga_suspend, rga_resume)
> +       SET_RUNTIME_PM_OPS(rga_runtime_suspend,
> +                          rga_runtime_resume, NULL)
> +};
> +
> +static struct platform_driver rga_pltfm_driver = {
> +       .probe  = rga_probe,
> +       .remove = rga_remove,
> +       .driver = {
> +               .name = "rockchip-rga",
> +               .pm = &rga_pm,
> +               .of_match_table = rockchip_rga_dt_ids,
> +       },
> +};
> +
> +module_platform_driver(rga_pltfm_driver);
> +
> +MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
> +MODULE_DESCRIPTION("Rockchip RGA Driver Extension");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:rockchip-rga");
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_rga.h b/drivers/gpu/drm/rockchip/rockchip_drm_rga.h
> new file mode 100644
> index 0000000..4a8839a
> --- /dev/null
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_rga.h
> @@ -0,0 +1,108 @@
> +#ifndef __ROCKCHIP_DRM_RGA__
> +#define __ROCKCHIP_DRM_RGA__
> +
> +#define RGA_CMDBUF_SIZE                        14
> +#define RGA_CMDLIST_SIZE               0x20
> +#define RGA_CMDLIST_NUM                        64
> +
> +/* cmdlist data structure */
> +struct rga_cmdlist {
> +       u32             head;
> +       unsigned long   data[RGA_CMDLIST_SIZE * 2];
> +       u32             last;   /* last data offset */
> +       void            *src_mmu_pages;
> +       void            *dst_mmu_pages;
> +       void            *src1_mmu_pages;
> +       struct dma_buf_attachment *src_attach;
> +       struct dma_buf_attachment *dst_attach;
> +};
> +
> +struct rga_cmdlist_node {
> +       struct list_head        list;
> +       struct rga_cmdlist      cmdlist;
> +};
> +
> +struct rga_runqueue_node {
> +       struct list_head        list;
> +
> +       struct device           *dev;
> +       pid_t                   pid;
> +       struct drm_file         *file;
> +       struct completion       complete;
> +
> +       struct list_head        run_cmdlist;
> +
> +       int                     cmdlist_cnt;
> +       void                    *cmdlist_pool_virt;
> +       dma_addr_t              cmdlist_pool;
> +       struct dma_attrs        cmdlist_dma_attrs;
> +};
> +
> +struct rockchip_rga_version {
> +       __u32                   major;
> +       __u32                   minor;
> +};
> +
> +struct rockchip_rga {
> +       struct drm_device       *drm_dev;
> +       struct device           *dev;
> +       struct regmap           *grf;
> +       void __iomem            *regs;
> +       struct clk              *sclk;
> +       struct clk              *aclk;
> +       struct clk              *hclk;
> +
> +       bool                            suspended;
> +       struct rockchip_rga_version     version;
> +       struct drm_rockchip_subdrv      subdrv;
> +       struct workqueue_struct         *rga_workq;
> +       struct work_struct              runqueue_work;
> +
> +       /* rga command list pool */
> +       struct rga_cmdlist_node         cmdlist_node[RGA_CMDLIST_NUM];
> +       struct mutex                    cmdlist_mutex;
> +
> +       struct list_head                free_cmdlist;
> +
> +       /* rga runqueue */
> +       struct rga_runqueue_node        *runqueue_node;
> +       struct list_head                runqueue_list;
> +       struct mutex                    runqueue_mutex;
> +       struct kmem_cache               *runqueue_slab;
> +};
> +
> +struct rockchip_drm_rga_private {
> +       struct device           *dev;
> +       struct list_head        inuse_cmdlist;
> +       struct list_head        userptr_list;
> +};
> +
> +#ifdef CONFIG_ROCKCHIP_DRM_RGA
> +int rockchip_rga_get_ver_ioctl(struct drm_device *dev, void *data,
> +                              struct drm_file *file_priv);
> +int rockchip_rga_set_cmdlist_ioctl(struct drm_device *dev, void *data,
> +                                  struct drm_file *file_priv);
> +int rockchip_rga_exec_ioctl(struct drm_device *dev, void *data,
> +                           struct drm_file *file_priv);
> +#else
> +static inline int rockchip_rga_get_ver_ioctl(struct drm_device *dev, void *data,
> +                                            struct drm_file *file_priv)
> +{
> +       return -ENODEV;
> +}
> +
> +static inline int rockchip_rga_set_cmdlist_ioctl(struct drm_device *dev,
> +                                                void *data,
> +                                                struct drm_file *file_priv)
> +{
> +       return -ENODEV;
> +}
> +
> +static inline int rockchip_rga_exec_ioctl(struct drm_device *dev, void *data,
> +                                         struct drm_file *file_priv)
> +{
> +       return -ENODEV;
> +}
> +#endif
> +
> +#endif /* __ROCKCHIP_DRM_RGA__ */
> diff --git a/include/uapi/drm/rockchip_drm.h b/include/uapi/drm/rockchip_drm.h
> new file mode 100644
> index 0000000..2e3e240
> --- /dev/null
> +++ b/include/uapi/drm/rockchip_drm.h
> @@ -0,0 +1,63 @@
> +/* rockchip_drm.h
> + *
> + * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd.
> + * Authors:
> + *     Yakir Yang <ykk@rock-chips.com>
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + */
> +
> +#ifndef _UAPI_ROCKCHIP_DRM_H_
> +#define _UAPI_ROCKCHIP_DRM_H_
> +
> +#include <drm/drm.h>
> +
> +struct drm_rockchip_rga_get_ver {
> +       __u32   major;
> +       __u32   minor;
> +};
> +
> +struct drm_rockchip_rga_cmd {
> +       __u32   offset;
> +       __u32   data;
> +};
> +
> +enum drm_rockchip_rga_buf_type {
> +       RGA_BUF_TYPE_USERPTR = 1 << 31,
> +       RGA_BUF_TYPE_GEMFD   = 1 << 30,
> +};
> +
> +struct drm_rockchip_rga_userptr {
> +       unsigned long userptr;
> +       unsigned long size;
> +};
> +
> +struct drm_rockchip_rga_set_cmdlist {
> +       __u64           cmd;
> +       __u64           cmd_buf;
> +       __u32           cmd_nr;
> +       __u32           cmd_buf_nr;
> +       __u64           user_data;
> +};
> +
> +struct drm_rockchip_rga_exec {
> +       __u64           async;
> +};
> +
> +#define DRM_ROCKCHIP_RGA_GET_VER               0x20
> +#define DRM_ROCKCHIP_RGA_SET_CMDLIST           0x21
> +#define DRM_ROCKCHIP_RGA_EXEC                  0x22
> +
> +#define DRM_IOCTL_ROCKCHIP_RGA_GET_VER         DRM_IOWR(DRM_COMMAND_BASE + \
> +       DRM_ROCKCHIP_RGA_GET_VER, struct drm_rockchip_rga_get_ver)
> +
> +#define DRM_IOCTL_ROCKCHIP_RGA_SET_CMDLIST     DRM_IOWR(DRM_COMMAND_BASE + \
> +       DRM_ROCKCHIP_RGA_SET_CMDLIST, struct drm_rockchip_rga_set_cmdlist)
> +
> +#define DRM_IOCTL_ROCKCHIP_RGA_EXEC            DRM_IOWR(DRM_COMMAND_BASE + \
> +       DRM_ROCKCHIP_RGA_EXEC, struct drm_rockchip_rga_exec)
> +
> +#endif /* _UAPI_ROCKCHIP_DRM_H */
> --
> 1.9.1
>
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-30 20:03                       ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-30 20:03 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Yakir Yang, David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	LAKML

On 29 March 2016 at 14:13, Emil Velikov <emil.l.velikov@gmail.com> wrote:
> On 28 March 2016 at 23:13, Heiko Stübner <heiko@sntech.de> wrote:
>
>> I have the feeling we're going quite a bit off-topic right now :-) .
>> The binary-driver-crazyness, hasn't really anything to do with Yakir's support
>> for the RGA (which is about raster-graphics-acceleration, so 2d stuff).
>>
>> And me mentioning the armsoc-ddx was merely a means to allow some sort of
>> different userspace user, as requested in your original mail ;-) .
>>
> Seems like I forgot to state the obvious - for all the reasons
> mentioned, the armsoc ddx seems like a bad example.
>
>> Maybe you know a better use-case on where to demonstrate the viability of the
>> userspace API for it as originally requested.
> I'm afraid that my RockChip-foo is extremely limited. Perhaps the
> actual user of these should be mentioned ? xf86-video-rockhip (is
> there one ?) or any other effort/project that lacks some (all?) of the
> criticism listed.
>
> (Sort of) the bottom line - either reuse the existing interfaces or
> provide an approved, full blown userspace (libdrm demos/programs do
> not count) that uses the new interfaces.
>
> I haven't made these rules, just a fool^Wguy that repeats them so that
> people don't abuse them much. If in doubt check with Dave and Daniel V
> - they had enough repeating these.
>
I can see how my earlier response may have been come
across/interpreted as aggressive and/or demanding. Apologies anyone
got upset/annoyed.

Let me try in another light - if you guys are willing to have
xf86-video-rockchip or keep track of/co-maintain armsoc, pretty much
everyone will be over the moon. Personally I'd opt for the former,
taking the modesetting (the one in the xserver tree) as a base - it
has all the cool new bits ;-)

Regards,
Emil

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-30 20:03                       ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-30 20:03 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Yakir Yang, David Airlie, Mark Yao, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	LAKML

On 29 March 2016 at 14:13, Emil Velikov <emil.l.velikov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On 28 March 2016 at 23:13, Heiko Stübner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org> wrote:
>
>> I have the feeling we're going quite a bit off-topic right now :-) .
>> The binary-driver-crazyness, hasn't really anything to do with Yakir's support
>> for the RGA (which is about raster-graphics-acceleration, so 2d stuff).
>>
>> And me mentioning the armsoc-ddx was merely a means to allow some sort of
>> different userspace user, as requested in your original mail ;-) .
>>
> Seems like I forgot to state the obvious - for all the reasons
> mentioned, the armsoc ddx seems like a bad example.
>
>> Maybe you know a better use-case on where to demonstrate the viability of the
>> userspace API for it as originally requested.
> I'm afraid that my RockChip-foo is extremely limited. Perhaps the
> actual user of these should be mentioned ? xf86-video-rockhip (is
> there one ?) or any other effort/project that lacks some (all?) of the
> criticism listed.
>
> (Sort of) the bottom line - either reuse the existing interfaces or
> provide an approved, full blown userspace (libdrm demos/programs do
> not count) that uses the new interfaces.
>
> I haven't made these rules, just a fool^Wguy that repeats them so that
> people don't abuse them much. If in doubt check with Dave and Daniel V
> - they had enough repeating these.
>
I can see how my earlier response may have been come
across/interpreted as aggressive and/or demanding. Apologies anyone
got upset/annoyed.

Let me try in another light - if you guys are willing to have
xf86-video-rockchip or keep track of/co-maintain armsoc, pretty much
everyone will be over the moon. Personally I'd opt for the former,
taking the modesetting (the one in the xserver tree) as a base - it
has all the cool new bits ;-)

Regards,
Emil
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-03-30 20:03                       ` Emil Velikov
  0 siblings, 0 replies; 73+ messages in thread
From: Emil Velikov @ 2016-03-30 20:03 UTC (permalink / raw)
  To: linux-arm-kernel

On 29 March 2016 at 14:13, Emil Velikov <emil.l.velikov@gmail.com> wrote:
> On 28 March 2016 at 23:13, Heiko St?bner <heiko@sntech.de> wrote:
>
>> I have the feeling we're going quite a bit off-topic right now :-) .
>> The binary-driver-crazyness, hasn't really anything to do with Yakir's support
>> for the RGA (which is about raster-graphics-acceleration, so 2d stuff).
>>
>> And me mentioning the armsoc-ddx was merely a means to allow some sort of
>> different userspace user, as requested in your original mail ;-) .
>>
> Seems like I forgot to state the obvious - for all the reasons
> mentioned, the armsoc ddx seems like a bad example.
>
>> Maybe you know a better use-case on where to demonstrate the viability of the
>> userspace API for it as originally requested.
> I'm afraid that my RockChip-foo is extremely limited. Perhaps the
> actual user of these should be mentioned ? xf86-video-rockhip (is
> there one ?) or any other effort/project that lacks some (all?) of the
> criticism listed.
>
> (Sort of) the bottom line - either reuse the existing interfaces or
> provide an approved, full blown userspace (libdrm demos/programs do
> not count) that uses the new interfaces.
>
> I haven't made these rules, just a fool^Wguy that repeats them so that
> people don't abuse them much. If in doubt check with Dave and Daniel V
> - they had enough repeating these.
>
I can see how my earlier response may have been come
across/interpreted as aggressive and/or demanding. Apologies anyone
got upset/annoyed.

Let me try in another light - if you guys are willing to have
xf86-video-rockchip or keep track of/co-maintain armsoc, pretty much
everyone will be over the moon. Personally I'd opt for the former,
taking the modesetting (the one in the xserver tree) as a base - it
has all the cool new bits ;-)

Regards,
Emil

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
  2016-03-30 20:03                       ` Emil Velikov
  (?)
@ 2016-04-05  1:13                         ` Mark yao
  -1 siblings, 0 replies; 73+ messages in thread
From: Mark yao @ 2016-04-05  1:13 UTC (permalink / raw)
  To: Emil Velikov, Heiko Stübner
  Cc: Yakir Yang, David Airlie, Joonyoung Shim, Kumar Gala,
	Ian Campbell, Rob Herring, Pawel Moll, Russell King, devicetree,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	LAKML

On 2016年03月31日 04:03, Emil Velikov wrote:
> On 29 March 2016 at 14:13, Emil Velikov <emil.l.velikov@gmail.com> wrote:
>> On 28 March 2016 at 23:13, Heiko Stübner <heiko@sntech.de> wrote:
>>
>>> I have the feeling we're going quite a bit off-topic right now :-) .
>>> The binary-driver-crazyness, hasn't really anything to do with Yakir's support
>>> for the RGA (which is about raster-graphics-acceleration, so 2d stuff).
>>>
>>> And me mentioning the armsoc-ddx was merely a means to allow some sort of
>>> different userspace user, as requested in your original mail ;-) .
>>>
>> Seems like I forgot to state the obvious - for all the reasons
>> mentioned, the armsoc ddx seems like a bad example.
>>
>>> Maybe you know a better use-case on where to demonstrate the viability of the
>>> userspace API for it as originally requested.
>> I'm afraid that my RockChip-foo is extremely limited. Perhaps the
>> actual user of these should be mentioned ? xf86-video-rockhip (is
>> there one ?) or any other effort/project that lacks some (all?) of the
>> criticism listed.
>>
>> (Sort of) the bottom line - either reuse the existing interfaces or
>> provide an approved, full blown userspace (libdrm demos/programs do
>> not count) that uses the new interfaces.
>>
>> I haven't made these rules, just a fool^Wguy that repeats them so that
>> people don't abuse them much. If in doubt check with Dave and Daniel V
>> - they had enough repeating these.
>>
> I can see how my earlier response may have been come
> across/interpreted as aggressive and/or demanding. Apologies anyone
> got upset/annoyed.
>
> Let me try in another light - if you guys are willing to have
> xf86-video-rockchip or keep track of/co-maintain armsoc, pretty much
> everyone will be over the moon. Personally I'd opt for the former,
> taking the modesetting (the one in the xserver tree) as a base - it
> has all the cool new bits ;-)
>
> Regards,
> Emil
>
>
>

I'd like to use modesetting more than armsoc. the modesetting seems more 
stable and it support glamor(2d acceleration with gpu).

We have some work on modesetting ddx, with some hack, both 3d dri2 and 
glamor 2d acceleration can works with mali gpu.

So if Yakir want to support EXA on ddx, I hope he can use modesetting.


Thanks.

-- 
Mark Yao

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-04-05  1:13                         ` Mark yao
  0 siblings, 0 replies; 73+ messages in thread
From: Mark yao @ 2016-04-05  1:13 UTC (permalink / raw)
  To: Emil Velikov, Heiko Stübner
  Cc: devicetree, Russell King, Pawel Moll, Ian Campbell,
	Linux-Kernel@Vger. Kernel. Org, ML dri-devel, linux-rockchip,
	Rob Herring, Kumar Gala, LAKML

On 2016年03月31日 04:03, Emil Velikov wrote:
> On 29 March 2016 at 14:13, Emil Velikov <emil.l.velikov@gmail.com> wrote:
>> On 28 March 2016 at 23:13, Heiko Stübner <heiko@sntech.de> wrote:
>>
>>> I have the feeling we're going quite a bit off-topic right now :-) .
>>> The binary-driver-crazyness, hasn't really anything to do with Yakir's support
>>> for the RGA (which is about raster-graphics-acceleration, so 2d stuff).
>>>
>>> And me mentioning the armsoc-ddx was merely a means to allow some sort of
>>> different userspace user, as requested in your original mail ;-) .
>>>
>> Seems like I forgot to state the obvious - for all the reasons
>> mentioned, the armsoc ddx seems like a bad example.
>>
>>> Maybe you know a better use-case on where to demonstrate the viability of the
>>> userspace API for it as originally requested.
>> I'm afraid that my RockChip-foo is extremely limited. Perhaps the
>> actual user of these should be mentioned ? xf86-video-rockhip (is
>> there one ?) or any other effort/project that lacks some (all?) of the
>> criticism listed.
>>
>> (Sort of) the bottom line - either reuse the existing interfaces or
>> provide an approved, full blown userspace (libdrm demos/programs do
>> not count) that uses the new interfaces.
>>
>> I haven't made these rules, just a fool^Wguy that repeats them so that
>> people don't abuse them much. If in doubt check with Dave and Daniel V
>> - they had enough repeating these.
>>
> I can see how my earlier response may have been come
> across/interpreted as aggressive and/or demanding. Apologies anyone
> got upset/annoyed.
>
> Let me try in another light - if you guys are willing to have
> xf86-video-rockchip or keep track of/co-maintain armsoc, pretty much
> everyone will be over the moon. Personally I'd opt for the former,
> taking the modesetting (the one in the xserver tree) as a base - it
> has all the cool new bits ;-)
>
> Regards,
> Emil
>
>
>

I'd like to use modesetting more than armsoc. the modesetting seems more 
stable and it support glamor(2d acceleration with gpu).

We have some work on modesetting ddx, with some hack, both 3d dri2 and 
glamor 2d acceleration can works with mali gpu.

So if Yakir want to support EXA on ddx, I hope he can use modesetting.


Thanks.

-- 
Mark Yao


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [RFC PATCH v1 0/4] Add Rockchip RGA support
@ 2016-04-05  1:13                         ` Mark yao
  0 siblings, 0 replies; 73+ messages in thread
From: Mark yao @ 2016-04-05  1:13 UTC (permalink / raw)
  To: linux-arm-kernel

On 2016?03?31? 04:03, Emil Velikov wrote:
> On 29 March 2016 at 14:13, Emil Velikov <emil.l.velikov@gmail.com> wrote:
>> On 28 March 2016 at 23:13, Heiko St?bner <heiko@sntech.de> wrote:
>>
>>> I have the feeling we're going quite a bit off-topic right now :-) .
>>> The binary-driver-crazyness, hasn't really anything to do with Yakir's support
>>> for the RGA (which is about raster-graphics-acceleration, so 2d stuff).
>>>
>>> And me mentioning the armsoc-ddx was merely a means to allow some sort of
>>> different userspace user, as requested in your original mail ;-) .
>>>
>> Seems like I forgot to state the obvious - for all the reasons
>> mentioned, the armsoc ddx seems like a bad example.
>>
>>> Maybe you know a better use-case on where to demonstrate the viability of the
>>> userspace API for it as originally requested.
>> I'm afraid that my RockChip-foo is extremely limited. Perhaps the
>> actual user of these should be mentioned ? xf86-video-rockhip (is
>> there one ?) or any other effort/project that lacks some (all?) of the
>> criticism listed.
>>
>> (Sort of) the bottom line - either reuse the existing interfaces or
>> provide an approved, full blown userspace (libdrm demos/programs do
>> not count) that uses the new interfaces.
>>
>> I haven't made these rules, just a fool^Wguy that repeats them so that
>> people don't abuse them much. If in doubt check with Dave and Daniel V
>> - they had enough repeating these.
>>
> I can see how my earlier response may have been come
> across/interpreted as aggressive and/or demanding. Apologies anyone
> got upset/annoyed.
>
> Let me try in another light - if you guys are willing to have
> xf86-video-rockchip or keep track of/co-maintain armsoc, pretty much
> everyone will be over the moon. Personally I'd opt for the former,
> taking the modesetting (the one in the xserver tree) as a base - it
> has all the cool new bits ;-)
>
> Regards,
> Emil
>
>
>

I'd like to use modesetting more than armsoc. the modesetting seems more 
stable and it support glamor(2d acceleration with gpu).

We have some work on modesetting ddx, with some hack, both 3d dri2 and 
glamor 2d acceleration can works with mali gpu.

So if Yakir want to support EXA on ddx, I hope he can use modesetting.


Thanks.

-- 
?ark Yao

^ permalink raw reply	[flat|nested] 73+ messages in thread

end of thread, other threads:[~2016-04-05  1:13 UTC | newest]

Thread overview: 73+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-21  9:28 [RFC PATCH v1 0/4] Add Rockchip RGA support Yakir Yang
2016-03-21  9:28 ` Yakir Yang
2016-03-21  9:28 ` Yakir Yang
2016-03-21  9:38 ` [RFC PATCH v1 1/4] drm: rockchip: add a common subdrv interfaces Yakir Yang
2016-03-21  9:38   ` Yakir Yang
2016-03-21  9:38   ` Yakir Yang
2016-03-21  9:40 ` [RFC PATCH v1 2/4] drm: rockchip: add RGA driver support Yakir Yang
2016-03-21  9:40   ` Yakir Yang
2016-03-21  9:40   ` Yakir Yang
     [not found]   ` <20160323142021.GA19977@rob-hp-laptop>
2016-03-29 11:50     ` Yakir Yang
2016-03-30 18:34   ` Rob Clark
2016-03-30 18:34     ` Rob Clark
2016-03-30 18:34     ` Rob Clark
2016-03-21  9:42 ` [RFC PATCH v1 3/4] ARM: dts: rockchip: add RGA device node for RK3288 Yakir Yang
2016-03-21  9:42   ` Yakir Yang
2016-03-21  9:42   ` Yakir Yang
2016-03-21  9:42 ` [RFC PATCH v1 4/4] ARM: dst: rockchip: enable RGA support on veyron devices Yakir Yang
2016-03-21  9:42   ` Yakir Yang
2016-03-21  9:42   ` Yakir Yang
2016-03-21 11:29 ` [RFC PATCH v1 0/4] Add Rockchip RGA support Heiko Stübner
2016-03-21 11:29   ` Heiko Stübner
2016-03-21 11:29   ` Heiko Stübner
2016-03-21 12:17   ` Yakir Yang
2016-03-21 12:17     ` Yakir Yang
2016-03-21 12:17     ` Yakir Yang
2016-03-22  0:42     ` Heiko Stuebner
2016-03-22  0:42       ` Heiko Stuebner
2016-03-22  0:42       ` Heiko Stuebner
2016-03-22  2:14       ` Yakir Yang
2016-03-22  2:14         ` Yakir Yang
2016-03-22  2:14         ` Yakir Yang
2016-03-28 12:21       ` Emil Velikov
2016-03-28 12:21         ` Emil Velikov
2016-03-28 12:21         ` Emil Velikov
2016-03-28 18:44         ` Heiko Stübner
2016-03-28 18:44           ` Heiko Stübner
2016-03-28 18:44           ` Heiko Stübner
2016-03-28 21:35           ` Emil Velikov
2016-03-28 21:35             ` Emil Velikov
2016-03-28 21:35             ` Emil Velikov
2016-03-28 21:46             ` Heiko Stübner
2016-03-28 21:46               ` Heiko Stübner
2016-03-28 21:46               ` Heiko Stübner
2016-03-28 22:07               ` Emil Velikov
2016-03-28 22:07                 ` Emil Velikov
2016-03-28 22:07                 ` Emil Velikov
2016-03-28 22:13                 ` Heiko Stübner
2016-03-28 22:13                   ` Heiko Stübner
2016-03-29 13:13                   ` Emil Velikov
2016-03-29 13:13                     ` Emil Velikov
2016-03-29 13:13                     ` Emil Velikov
2016-03-30 20:03                     ` Emil Velikov
2016-03-30 20:03                       ` Emil Velikov
2016-03-30 20:03                       ` Emil Velikov
2016-04-05  1:13                       ` Mark yao
2016-04-05  1:13                         ` Mark yao
2016-04-05  1:13                         ` Mark yao
2016-03-29 11:17             ` Yakir Yang
2016-03-29 11:17               ` Yakir Yang
2016-03-29 11:17               ` Yakir Yang
2016-03-29 11:47               ` Heiko Stübner
2016-03-29 11:47                 ` Heiko Stübner
2016-03-29 11:40         ` Yakir Yang
2016-03-29 11:40           ` Yakir Yang
2016-03-29 11:40           ` Yakir Yang
2016-03-29 13:27           ` Emil Velikov
2016-03-29 13:27             ` Emil Velikov
2016-03-29 13:27             ` Emil Velikov
2016-03-22 10:24     ` Andreas Färber
2016-03-22 10:24       ` Andreas Färber
2016-03-29 11:45       ` Yakir Yang
2016-03-29 11:45         ` Yakir Yang
2016-03-29 11:45         ` Yakir Yang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.