All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem
@ 2015-11-30 13:53 Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 01/22] drm/exynos: gsc: prepare and unprepare gsc clock Marek Szyprowski
                   ` (22 more replies)
  0 siblings, 23 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

Dear All,

This patch series introduces a new life into Exynos IPP (Image Post
Processing) subsystem by integrating it (transparently for userspace
applications) with Exynos DRM core plane management. This means that all
CRTC drivers transparently get support for standard features of IPP
subsystem like rotation, scaling and color space conversion.

Support for features not supported natively by CRTC drivers is
implemented with a help of temporary framebuffers, where image data is
processed by IPP subsystem before performing the scanout by a CRTC driver.

This is second version of this patchset. The initial version is available
here:
http://thread.gmane.org/gmane.linux.kernel.samsung-soc/49743

The main change since v1 is support for color space conversion and minor
fixes in the preparation patches (added support for native scaling in
Exynos Video Processor module).

This feature is 'experimental'. From the initial discussion I see that
there is no consensus if this feature should be integrated seamplessly
in Exynos DRM core or provided by a separate API. This will be further
discussed.

However, I would like to ask for merging patches 1-15, which are pure
bugfixes and code cleanups. The patches are based on top of current
exynos-drm-next branch.

Best regards
Marek Szyprowski
Samsung R&D Institute Poland


Patch summary:

Marek Szyprowski (17):
  drm/exynos: rotator: convert to common clock framework
  drm/exynos: exynos7-decon: remove excessive check
  drm/exynos: move dma_addr attribute from exynos plane to exynos fb
  drm/exynos: introduce exynos_drm_plane_state structure
  drm/exynos: mixer: use crtc->state->adjusted_mode instead of
    crtc->mode
  drm/exynos: mixer: enable video overlay plane only when VP is
    available
  drm/exynos: introduce exynos_drm_plane_config structure
  drm/exynos: add generic check for plane state
  drm/exynos: mixer: use ratio precalculated in exynos_state
  drm/exynos: fix clipping when scaling is enabled
  drm/exynos: fimd: fix dma burst size setting for small plane size
  drm/exynos: gem: remove old unused prototypes
  drm/exynos: add fb pointer to exynos_drm_plane_state
  drm/exynos: gem: set default alignment for dumb GEM buffers
  drm/exynos: gem: simplify access to exynos gem object
  drm/exynos: ipp: make framework context global
  drm/exynos: add support for plane rotation, scalling and colospace
    convesion

Seung-Woo Kim (5):
  drm/exynos: gsc: prepare and unprepare gsc clock
  drm/exynos: gsc: fix wrong pm_runtime state
  drm/exynos: gsc: add device tree support and remove usage of static
    mappings
  drm/exynos: fix to calculate offset of each plane for ipp fimc
  drm/exynos: fix to calculate offset of each plane for ipp gsc

 .../devicetree/bindings/media/exynos5-gsc.txt      |   4 +
 drivers/gpu/drm/exynos/Kconfig                     |  10 +-
 drivers/gpu/drm/exynos/Makefile                    |   1 +
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c      |  48 ++-
 drivers/gpu/drm/exynos/exynos7_drm_decon.c         |  68 ++--
 drivers/gpu/drm/exynos/exynos_drm_drv.h            |  96 ++++--
 drivers/gpu/drm/exynos/exynos_drm_fb.c             |  16 +-
 drivers/gpu/drm/exynos/exynos_drm_fb.h             |   3 +-
 drivers/gpu/drm/exynos/exynos_drm_fimc.c           | 106 ++++++
 drivers/gpu/drm/exynos/exynos_drm_fimd.c           |  88 ++---
 drivers/gpu/drm/exynos/exynos_drm_g2d.c            |  48 ++-
 drivers/gpu/drm/exynos/exynos_drm_gem.c            |  54 +--
 drivers/gpu/drm/exynos/exynos_drm_gem.h            |  51 +--
 drivers/gpu/drm/exynos/exynos_drm_gsc.c            | 151 ++++++++-
 drivers/gpu/drm/exynos/exynos_drm_ipp.c            | 240 +++++++++++---
 drivers/gpu/drm/exynos/exynos_drm_ipp.h            |   8 +-
 drivers/gpu/drm/exynos/exynos_drm_plane.c          | 237 ++++++++-----
 drivers/gpu/drm/exynos/exynos_drm_plane.h          |   7 +-
 drivers/gpu/drm/exynos/exynos_drm_plane_ipp.c      | 369 +++++++++++++++++++++
 drivers/gpu/drm/exynos/exynos_drm_plane_ipp.h      |  73 ++++
 drivers/gpu/drm/exynos/exynos_drm_rotator.c        |   4 +-
 drivers/gpu/drm/exynos/exynos_drm_vidi.c           |  30 +-
 drivers/gpu/drm/exynos/exynos_mixer.c              | 129 ++++---
 drivers/gpu/drm/exynos/regs-gsc.h                  |   4 +-
 24 files changed, 1375 insertions(+), 470 deletions(-)
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_plane_ipp.c
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_plane_ipp.h

-- 
1.9.2

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

* [PATCH v2 01/22] drm/exynos: gsc: prepare and unprepare gsc clock
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 02/22] drm/exynos: gsc: fix wrong pm_runtime state Marek Szyprowski
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

From: Seung-Woo Kim <sw0312.kim@samsung.com>

Ths patch changes the clk_enable and clk_disable call in gsc driver
into clk_prepare_enable and clk_disable_unprepare.

Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_gsc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 11b87d2a7913..72a9c84e06b6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -1215,10 +1215,10 @@ static int gsc_clk_ctrl(struct gsc_context *ctx, bool enable)
 	DRM_DEBUG_KMS("enable[%d]\n", enable);
 
 	if (enable) {
-		clk_enable(ctx->gsc_clk);
+		clk_prepare_enable(ctx->gsc_clk);
 		ctx->suspended = false;
 	} else {
-		clk_disable(ctx->gsc_clk);
+		clk_disable_unprepare(ctx->gsc_clk);
 		ctx->suspended = true;
 	}
 
-- 
1.9.2

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

* [PATCH v2 02/22] drm/exynos: gsc: fix wrong pm_runtime state
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 01/22] drm/exynos: gsc: prepare and unprepare gsc clock Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 03/22] drm/exynos: gsc: add device tree support and remove usage of static mappings Marek Szyprowski
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

From: Seung-Woo Kim <sw0312.kim@samsung.com>

At probe time, gsc clock is not enabled, so pm_runtime state should
be deactive. So this patch removes pm_runtime_set_active() from
gsc_probe().

Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_gsc.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 72a9c84e06b6..ed55d37b6330 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -1713,7 +1713,6 @@ static int gsc_probe(struct platform_device *pdev)
 	mutex_init(&ctx->lock);
 	platform_set_drvdata(pdev, ctx);
 
-	pm_runtime_set_active(dev);
 	pm_runtime_enable(dev);
 
 	ret = exynos_drm_ippdrv_register(ippdrv);
-- 
1.9.2

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

* [PATCH v2 03/22] drm/exynos: gsc: add device tree support and remove usage of static mappings
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 01/22] drm/exynos: gsc: prepare and unprepare gsc clock Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 02/22] drm/exynos: gsc: fix wrong pm_runtime state Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-12-10  6:48   ` Inki Dae
  2015-11-30 13:53 ` [PATCH v2 04/22] drm/exynos: rotator: convert to common clock framework Marek Szyprowski
                   ` (19 subsequent siblings)
  22 siblings, 1 reply; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

From: Seung-Woo Kim <sw0312.kim@samsung.com>

This patch adds device tree support for exynos_drm_gsc. This patch
also fixed build issue on non-Exynos platforms, thus dependency on
!ARCH_MULTIPLATFORM can be now removed. The driver cannot be used
simultaneously with V4L2 Mem2Mem GScaller driver thought.

Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
[updated commit message, removed the need for wb-lcd property, because
all gscallers have support for lcd writeback, replaced dependency on
!ARCH_MULTIPLATFORM with !VIDEO_SAMSUNG_EXYNOS_GSC]
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 .../devicetree/bindings/media/exynos5-gsc.txt      |  4 +++
 drivers/gpu/drm/exynos/Kconfig                     |  2 +-
 drivers/gpu/drm/exynos/exynos_drm_gsc.c            | 30 +++++++++++++++++++---
 drivers/gpu/drm/exynos/regs-gsc.h                  |  4 +--
 4 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/exynos5-gsc.txt b/Documentation/devicetree/bindings/media/exynos5-gsc.txt
index 0604d42f38d1..5fe9372abb37 100644
--- a/Documentation/devicetree/bindings/media/exynos5-gsc.txt
+++ b/Documentation/devicetree/bindings/media/exynos5-gsc.txt
@@ -7,6 +7,10 @@ Required properties:
 - reg: should contain G-Scaler physical address location and length.
 - interrupts: should contain G-Scaler interrupt number
 
+Optional properties:
+- samsung,sysreg: handle to syscon used to control the system registers to
+  set writeback input and destination
+
 Example:
 
 gsc_0:  gsc@0x13e00000 {
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 96e86cf4455b..83efca941388 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -118,7 +118,7 @@ config DRM_EXYNOS_ROTATOR
 
 config DRM_EXYNOS_GSC
 	bool "GScaler"
-	depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !ARCH_MULTIPLATFORM
+	depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !VIDEO_SAMSUNG_EXYNOS_GSC
 	help
 	  Choose this option if you want to use Exynos GSC for DRM.
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index ed55d37b6330..7aecd23cfa11 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -15,7 +15,8 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/pm_runtime.h>
-#include <plat/map-base.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 #include <drm/drmP.h>
 #include <drm/exynos_drm.h>
@@ -126,6 +127,7 @@ struct gsc_capability {
  * @ippdrv: prepare initialization using ippdrv.
  * @regs_res: register resources.
  * @regs: memory mapped io registers.
+ * @sysreg: handle to SYSREG block regmap.
  * @lock: locking of operations.
  * @gsc_clk: gsc gate clock.
  * @sc: scaler infomations.
@@ -138,6 +140,7 @@ struct gsc_context {
 	struct exynos_drm_ippdrv	ippdrv;
 	struct resource	*regs_res;
 	void __iomem	*regs;
+	struct regmap	*sysreg;
 	struct mutex	lock;
 	struct clk	*gsc_clk;
 	struct gsc_scaler	sc;
@@ -437,9 +440,12 @@ static int gsc_sw_reset(struct gsc_context *ctx)
 
 static void gsc_set_gscblk_fimd_wb(struct gsc_context *ctx, bool enable)
 {
-	u32 gscblk_cfg;
+	unsigned int gscblk_cfg;
 
-	gscblk_cfg = readl(SYSREG_GSCBLK_CFG1);
+	if (!ctx->sysreg)
+		return;
+
+	regmap_read(ctx->sysreg, SYSREG_GSCBLK_CFG1, &gscblk_cfg);
 
 	if (enable)
 		gscblk_cfg |= GSC_BLK_DISP1WB_DEST(ctx->id) |
@@ -448,7 +454,7 @@ static void gsc_set_gscblk_fimd_wb(struct gsc_context *ctx, bool enable)
 	else
 		gscblk_cfg |= GSC_BLK_PXLASYNC_LO_MASK_WB(ctx->id);
 
-	writel(gscblk_cfg, SYSREG_GSCBLK_CFG1);
+	regmap_write(ctx->sysreg, SYSREG_GSCBLK_CFG1, gscblk_cfg);
 }
 
 static void gsc_handle_irq(struct gsc_context *ctx, bool enable,
@@ -1663,6 +1669,15 @@ static int gsc_probe(struct platform_device *pdev)
 	if (!ctx)
 		return -ENOMEM;
 
+	if (dev->of_node) {
+		ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
+							"samsung,sysreg");
+		if (IS_ERR(ctx->sysreg)) {
+			dev_warn(dev, "failed to get system register.\n");
+			ctx->sysreg = NULL;
+		}
+	}
+
 	/* clock control */
 	ctx->gsc_clk = devm_clk_get(dev, "gscl");
 	if (IS_ERR(ctx->gsc_clk)) {
@@ -1796,6 +1811,12 @@ static const struct dev_pm_ops gsc_pm_ops = {
 	SET_RUNTIME_PM_OPS(gsc_runtime_suspend, gsc_runtime_resume, NULL)
 };
 
+static const struct of_device_id exynos_drm_gsc_of_match[] = {
+	{ .compatible = "samsung,exynos5-gsc" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, exynos_drm_gsc_of_match);
+
 struct platform_driver gsc_driver = {
 	.probe		= gsc_probe,
 	.remove		= gsc_remove,
@@ -1803,6 +1824,7 @@ struct platform_driver gsc_driver = {
 		.name	= "exynos-drm-gsc",
 		.owner	= THIS_MODULE,
 		.pm	= &gsc_pm_ops,
+		.of_match_table = of_match_ptr(exynos_drm_gsc_of_match),
 	},
 };
 
diff --git a/drivers/gpu/drm/exynos/regs-gsc.h b/drivers/gpu/drm/exynos/regs-gsc.h
index 9ad592707aaf..4704a993cbb7 100644
--- a/drivers/gpu/drm/exynos/regs-gsc.h
+++ b/drivers/gpu/drm/exynos/regs-gsc.h
@@ -273,12 +273,12 @@
 #define GSC_CLK_GATE_MODE_SNOOP_CNT(x)	((x) << 0)
 
 /* SYSCON. GSCBLK_CFG */
-#define SYSREG_GSCBLK_CFG1		(S3C_VA_SYS + 0x0224)
+#define SYSREG_GSCBLK_CFG1		0x0224
 #define GSC_BLK_DISP1WB_DEST(x)		(x << 10)
 #define GSC_BLK_SW_RESET_WB_DEST(x)	(1 << (18 + x))
 #define GSC_BLK_PXLASYNC_LO_MASK_WB(x)	(0 << (14 + x))
 #define GSC_BLK_GSCL_WB_IN_SRC_SEL(x)	(1 << (2 * x))
-#define SYSREG_GSCBLK_CFG2		(S3C_VA_SYS + 0x2000)
+#define SYSREG_GSCBLK_CFG2		0x2000
 #define PXLASYNC_LO_MASK_CAMIF_GSCL(x)	(1 << (x))
 
 #endif /* EXYNOS_REGS_GSC_H_ */
-- 
1.9.2

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

* [PATCH v2 04/22] drm/exynos: rotator: convert to common clock framework
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (2 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 03/22] drm/exynos: gsc: add device tree support and remove usage of static mappings Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 05/22] drm/exynos: exynos7-decon: remove excessive check Marek Szyprowski
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

This driver was not used after introduction of common clock framework.
This patch adds missing prepare/unprepare calls and allows to use it
again with current kernel code.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_rotator.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
index 2f5c118f4c8e..bea0f7826d30 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -790,10 +790,10 @@ static int rotator_remove(struct platform_device *pdev)
 static int rotator_clk_crtl(struct rot_context *rot, bool enable)
 {
 	if (enable) {
-		clk_enable(rot->clock);
+		clk_prepare_enable(rot->clock);
 		rot->suspended = false;
 	} else {
-		clk_disable(rot->clock);
+		clk_disable_unprepare(rot->clock);
 		rot->suspended = true;
 	}
 
-- 
1.9.2

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

* [PATCH v2 05/22] drm/exynos: exynos7-decon: remove excessive check
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (3 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 04/22] drm/exynos: rotator: convert to common clock framework Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 06/22] drm/exynos: move dma_addr attribute from exynos plane to exynos fb Marek Szyprowski
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

Display area is already checked by exynos plane core, so there is no
need for such check in driver code.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos7_drm_decon.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 38d7762ebdcb..4db04f244c17 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -394,7 +394,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 			       struct exynos_drm_plane *plane)
 {
 	struct decon_context *ctx = crtc->ctx;
-	struct drm_display_mode *mode = &crtc->base.state->adjusted_mode;
 	struct drm_plane_state *state = plane->base.state;
 	int padding;
 	unsigned long val, alpha;
@@ -436,15 +435,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
 			plane->crtc_w, plane->crtc_h);
 
-	/*
-	 * OSD position.
-	 * In case the window layout goes of LCD layout, DECON fails.
-	 */
-	if ((plane->crtc_x + plane->crtc_w) > mode->hdisplay)
-		plane->crtc_x = mode->hdisplay - plane->crtc_w;
-	if ((plane->crtc_y + plane->crtc_h) > mode->vdisplay)
-		plane->crtc_y = mode->vdisplay - plane->crtc_h;
-
 	val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
 		VIDOSDxA_TOPLEFT_Y(plane->crtc_y);
 	writel(val, ctx->regs + VIDOSD_A(win));
-- 
1.9.2

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

* [PATCH v2 06/22] drm/exynos: move dma_addr attribute from exynos plane to exynos fb
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (4 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 05/22] drm/exynos: exynos7-decon: remove excessive check Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-12-10 13:05   ` Inki Dae
  2015-11-30 13:53 ` [PATCH v2 07/22] drm/exynos: introduce exynos_drm_plane_state structure Marek Szyprowski
                   ` (16 subsequent siblings)
  22 siblings, 1 reply; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

DMA address is a framebuffer attribute and the right place for it is
exynos_drm_framebuffer not exynos_drm_plane. This patch also introduces
helper function for getting dma address of the given framebuffer.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 13 ++++++++-----
 drivers/gpu/drm/exynos/exynos7_drm_decon.c    | 16 +++++++++-------
 drivers/gpu/drm/exynos/exynos_drm_drv.h       |  3 ---
 drivers/gpu/drm/exynos/exynos_drm_fb.c        | 16 ++++++----------
 drivers/gpu/drm/exynos/exynos_drm_fb.h        |  3 +--
 drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 10 ++++++----
 drivers/gpu/drm/exynos/exynos_drm_plane.c     | 18 ------------------
 drivers/gpu/drm/exynos/exynos_drm_vidi.c      |  5 ++++-
 drivers/gpu/drm/exynos/exynos_mixer.c         |  7 ++++---
 9 files changed, 38 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index edfd6e390ef7..320efc3d0659 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -21,6 +21,7 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
+#include "exynos_drm_fb.h"
 #include "exynos_drm_plane.h"
 #include "exynos_drm_iommu.h"
 
@@ -261,9 +262,11 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 {
 	struct decon_context *ctx = crtc->ctx;
 	struct drm_plane_state *state = plane->base.state;
+	struct drm_framebuffer *fb = state->fb;
 	unsigned int win = plane->zpos;
-	unsigned int bpp = state->fb->bits_per_pixel >> 3;
-	unsigned int pitch = state->fb->pitches[0];
+	unsigned int bpp = fb->bits_per_pixel >> 3;
+	unsigned int pitch = fb->pitches[0];
+	dma_addr_t dma_addr = exynos_drm_fb_dma_addr(fb, 0);
 	u32 val;
 
 	if (test_bit(BIT_SUSPENDED, &ctx->flags))
@@ -284,9 +287,9 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 		VIDOSD_Wx_ALPHA_B_F(0x0);
 	writel(val, ctx->addr + DECON_VIDOSDxD(win));
 
-	writel(plane->dma_addr[0], ctx->addr + DECON_VIDW0xADD0B0(win));
+	writel(dma_addr, ctx->addr + DECON_VIDW0xADD0B0(win));
 
-	val = plane->dma_addr[0] + pitch * plane->crtc_h;
+	val = dma_addr + pitch * plane->crtc_h;
 	writel(val, ctx->addr + DECON_VIDW0xADD1B0(win));
 
 	if (ctx->out_type != IFTYPE_HDMI)
@@ -297,7 +300,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 			| BIT_VAL(plane->crtc_w * bpp, 14, 0);
 	writel(val, ctx->addr + DECON_VIDW0xADD2(win));
 
-	decon_win_set_pixfmt(ctx, win, state->fb);
+	decon_win_set_pixfmt(ctx, win, fb);
 
 	/* window enable */
 	decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, ~0);
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 4db04f244c17..1629732574e0 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -30,6 +30,7 @@
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_plane.h"
 #include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
 #include "exynos_drm_fbdev.h"
 #include "exynos_drm_iommu.h"
 
@@ -395,13 +396,14 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 {
 	struct decon_context *ctx = crtc->ctx;
 	struct drm_plane_state *state = plane->base.state;
+	struct drm_framebuffer *fb = state->fb;
 	int padding;
 	unsigned long val, alpha;
 	unsigned int last_x;
 	unsigned int last_y;
 	unsigned int win = plane->zpos;
-	unsigned int bpp = state->fb->bits_per_pixel >> 3;
-	unsigned int pitch = state->fb->pitches[0];
+	unsigned int bpp = fb->bits_per_pixel >> 3;
+	unsigned int pitch = fb->pitches[0];
 
 	if (ctx->suspended)
 		return;
@@ -417,14 +419,14 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 	 */
 
 	/* buffer start address */
-	val = (unsigned long)plane->dma_addr[0];
+	val = (unsigned long)exynos_drm_fb_dma_addr(fb, 0);
 	writel(val, ctx->regs + VIDW_BUF_START(win));
 
-	padding = (pitch / bpp) - state->fb->width;
+	padding = (pitch / bpp) - fb->width;
 
 	/* buffer size */
-	writel(state->fb->width + padding, ctx->regs + VIDW_WHOLE_X(win));
-	writel(state->fb->height, ctx->regs + VIDW_WHOLE_Y(win));
+	writel(fb->width + padding, ctx->regs + VIDW_WHOLE_X(win));
+	writel(fb->height, ctx->regs + VIDW_WHOLE_Y(win));
 
 	/* offset from the start of the buffer to read */
 	writel(plane->src_x, ctx->regs + VIDW_OFFSET_X(win));
@@ -466,7 +468,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 
 	writel(alpha, ctx->regs + VIDOSD_D(win));
 
-	decon_win_set_pixfmt(ctx, win, state->fb);
+	decon_win_set_pixfmt(ctx, win, fb);
 
 	/* hardware window 0 doesn't support color key. */
 	if (win != 0)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index f1eda7fa4e3c..dc41ffb26eb9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -54,8 +54,6 @@ enum exynos_drm_output_type {
  * @crtc_h: window height to be displayed (hardware screen).
  * @h_ratio: horizontal scaling ratio, 16.16 fixed point
  * @v_ratio: vertical scaling ratio, 16.16 fixed point
- * @dma_addr: array of bus(accessed by dma) address to the memory region
- *	      allocated for a overlay.
  * @zpos: order of overlay layer(z position).
  *
  * this structure is common to exynos SoC and its contents would be copied
@@ -74,7 +72,6 @@ struct exynos_drm_plane {
 	unsigned int crtc_h;
 	unsigned int h_ratio;
 	unsigned int v_ratio;
-	dma_addr_t dma_addr[MAX_FB_BUFFER];
 	unsigned int zpos;
 	struct drm_framebuffer *pending_fb;
 };
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 49b9bc302e87..f6bdb0d6f142 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -37,6 +37,7 @@
 struct exynos_drm_fb {
 	struct drm_framebuffer	fb;
 	struct exynos_drm_gem	*exynos_gem[MAX_FB_BUFFER];
+	dma_addr_t			dma_addr[MAX_FB_BUFFER];
 };
 
 static int check_fb_gem_memory_type(struct drm_device *drm_dev,
@@ -135,6 +136,8 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
 			goto err;
 
 		exynos_fb->exynos_gem[i] = exynos_gem[i];
+		exynos_fb->dma_addr[i] = exynos_gem[i]->dma_addr
+						+ mode_cmd->offsets[i];
 	}
 
 	drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
@@ -189,21 +192,14 @@ err:
 	return ERR_PTR(ret);
 }
 
-struct exynos_drm_gem *exynos_drm_fb_gem(struct drm_framebuffer *fb, int index)
+dma_addr_t exynos_drm_fb_dma_addr(struct drm_framebuffer *fb, int index)
 {
 	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
-	struct exynos_drm_gem *exynos_gem;
 
 	if (index >= MAX_FB_BUFFER)
-		return NULL;
+		return DMA_ERROR_CODE;
 
-	exynos_gem = exynos_fb->exynos_gem[index];
-	if (!exynos_gem)
-		return NULL;
-
-	DRM_DEBUG_KMS("dma_addr: 0x%lx\n", (unsigned long)exynos_gem->dma_addr);
-
-	return exynos_gem;
+	return exynos_fb->dma_addr[index];
 }
 
 static void exynos_drm_output_poll_changed(struct drm_device *dev)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h
index a8a75ac87e59..4aae9dd2b0d1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.h
@@ -22,8 +22,7 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
 			    struct exynos_drm_gem **exynos_gem,
 			    int count);
 
-/* get gem object of a drm framebuffer */
-struct exynos_drm_gem *exynos_drm_fb_gem(struct drm_framebuffer *fb, int index);
+dma_addr_t exynos_drm_fb_dma_addr(struct drm_framebuffer *fb, int index);
 
 void exynos_drm_mode_config_init(struct drm_device *dev);
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 2c383238efff..ffcc498f5afe 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -29,6 +29,7 @@
 #include <drm/exynos_drm.h>
 
 #include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
 #include "exynos_drm_fbdev.h"
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_plane.h"
@@ -642,12 +643,13 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
 {
 	struct fimd_context *ctx = crtc->ctx;
 	struct drm_plane_state *state = plane->base.state;
+	struct drm_framebuffer *fb = state->fb;
 	dma_addr_t dma_addr;
 	unsigned long val, size, offset;
 	unsigned int last_x, last_y, buf_offsize, line_size;
 	unsigned int win = plane->zpos;
-	unsigned int bpp = state->fb->bits_per_pixel >> 3;
-	unsigned int pitch = state->fb->pitches[0];
+	unsigned int bpp = fb->bits_per_pixel >> 3;
+	unsigned int pitch = fb->pitches[0];
 
 	if (ctx->suspended)
 		return;
@@ -656,7 +658,7 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
 	offset += plane->src_y * pitch;
 
 	/* buffer start address */
-	dma_addr = plane->dma_addr[0] + offset;
+	dma_addr = exynos_drm_fb_dma_addr(fb, 0) + offset;
 	val = (unsigned long)dma_addr;
 	writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
 
@@ -712,7 +714,7 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
 		DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
 	}
 
-	fimd_win_set_pixfmt(ctx, win, state->fb);
+	fimd_win_set_pixfmt(ctx, win, fb);
 
 	/* hardware window 0 doesn't support color key. */
 	if (win != 0)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 179311760bb7..c725409421b8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -120,28 +120,10 @@ static int exynos_plane_atomic_check(struct drm_plane *plane,
 				     struct drm_plane_state *state)
 {
 	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
-	int nr;
-	int i;
 
 	if (!state->fb)
 		return 0;
 
-	nr = drm_format_num_planes(state->fb->pixel_format);
-	for (i = 0; i < nr; i++) {
-		struct exynos_drm_gem *exynos_gem =
-					exynos_drm_fb_gem(state->fb, i);
-		if (!exynos_gem) {
-			DRM_DEBUG_KMS("gem object is null\n");
-			return -EFAULT;
-		}
-
-		exynos_plane->dma_addr[i] = exynos_gem->dma_addr +
-					    state->fb->offsets[i];
-
-		DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n",
-				i, (unsigned long)exynos_plane->dma_addr[i]);
-	}
-
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 669362c53f49..3ce141236fad 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -24,6 +24,7 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
+#include "exynos_drm_fb.h"
 #include "exynos_drm_plane.h"
 #include "exynos_drm_vidi.h"
 
@@ -126,11 +127,13 @@ static void vidi_update_plane(struct exynos_drm_crtc *crtc,
 			      struct exynos_drm_plane *plane)
 {
 	struct vidi_context *ctx = crtc->ctx;
+	dma_addr_t addr;
 
 	if (ctx->suspended)
 		return;
 
-	DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
+	addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
+	DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
 
 	if (ctx->vblank_on)
 		schedule_work(&ctx->work);
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 47777be1a754..f40de82848dc 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -37,6 +37,7 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
+#include "exynos_drm_fb.h"
 #include "exynos_drm_plane.h"
 #include "exynos_drm_iommu.h"
 
@@ -422,8 +423,8 @@ static void vp_video_buffer(struct mixer_context *ctx,
 		return;
 	}
 
-	luma_addr[0] = plane->dma_addr[0];
-	chroma_addr[0] = plane->dma_addr[1];
+	luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
+	chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
 
 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
 		ctx->interlace = true;
@@ -575,7 +576,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
 	dst_y_offset = plane->crtc_y;
 
 	/* converting dma address base and source offset */
-	dma_addr = plane->dma_addr[0]
+	dma_addr = exynos_drm_fb_dma_addr(fb, 0)
 		+ (plane->src_x * fb->bits_per_pixel >> 3)
 		+ (plane->src_y * fb->pitches[0]);
 	src_x_offset = 0;
-- 
1.9.2

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

* [PATCH v2 07/22] drm/exynos: introduce exynos_drm_plane_state structure
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (5 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 06/22] drm/exynos: move dma_addr attribute from exynos plane to exynos fb Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 08/22] drm/exynos: mixer: use crtc->state->adjusted_mode instead of crtc->mode Marek Szyprowski
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

This patch introduces exynos_drm_plane_state structure, which subclasses
drm_plane_state and holds precalculated data suitable for configuring
Exynos hardware.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c |  21 ++---
 drivers/gpu/drm/exynos/exynos7_drm_decon.c    |  21 ++---
 drivers/gpu/drm/exynos/exynos_drm_drv.h       |  56 +++++++-----
 drivers/gpu/drm/exynos/exynos_drm_fimd.c      |  33 +++----
 drivers/gpu/drm/exynos/exynos_drm_plane.c     | 125 +++++++++++++++++++-------
 drivers/gpu/drm/exynos/exynos_mixer.c         |  61 +++++++------
 6 files changed, 197 insertions(+), 120 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 320efc3d0659..12f558fc3ef6 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -260,9 +260,10 @@ static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
 static void decon_update_plane(struct exynos_drm_crtc *crtc,
 			       struct exynos_drm_plane *plane)
 {
+	struct exynos_drm_plane_state *state =
+				to_exynos_plane_state(plane->base.state);
 	struct decon_context *ctx = crtc->ctx;
-	struct drm_plane_state *state = plane->base.state;
-	struct drm_framebuffer *fb = state->fb;
+	struct drm_framebuffer *fb = state->base.fb;
 	unsigned int win = plane->zpos;
 	unsigned int bpp = fb->bits_per_pixel >> 3;
 	unsigned int pitch = fb->pitches[0];
@@ -272,11 +273,11 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 	if (test_bit(BIT_SUSPENDED, &ctx->flags))
 		return;
 
-	val = COORDINATE_X(plane->crtc_x) | COORDINATE_Y(plane->crtc_y);
+	val = COORDINATE_X(state->crtc.x) | COORDINATE_Y(state->crtc.y);
 	writel(val, ctx->addr + DECON_VIDOSDxA(win));
 
-	val = COORDINATE_X(plane->crtc_x + plane->crtc_w - 1) |
-		COORDINATE_Y(plane->crtc_y + plane->crtc_h - 1);
+	val = COORDINATE_X(state->crtc.x + state->crtc.w - 1) |
+		COORDINATE_Y(state->crtc.y + state->crtc.h - 1);
 	writel(val, ctx->addr + DECON_VIDOSDxB(win));
 
 	val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
@@ -289,15 +290,15 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 
 	writel(dma_addr, ctx->addr + DECON_VIDW0xADD0B0(win));
 
-	val = dma_addr + pitch * plane->crtc_h;
+	val = dma_addr + pitch * state->src.h;
 	writel(val, ctx->addr + DECON_VIDW0xADD1B0(win));
 
 	if (ctx->out_type != IFTYPE_HDMI)
-		val = BIT_VAL(pitch - plane->crtc_w * bpp, 27, 14)
-			| BIT_VAL(plane->crtc_w * bpp, 13, 0);
+		val = BIT_VAL(pitch - state->crtc.w * bpp, 27, 14)
+			| BIT_VAL(state->crtc.w * bpp, 13, 0);
 	else
-		val = BIT_VAL(pitch - plane->crtc_w * bpp, 29, 15)
-			| BIT_VAL(plane->crtc_w * bpp, 14, 0);
+		val = BIT_VAL(pitch - state->crtc.w * bpp, 29, 15)
+			| BIT_VAL(state->crtc.w * bpp, 14, 0);
 	writel(val, ctx->addr + DECON_VIDW0xADD2(win));
 
 	decon_win_set_pixfmt(ctx, win, fb);
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 1629732574e0..1c62de1a0839 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -394,9 +394,10 @@ static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
 static void decon_update_plane(struct exynos_drm_crtc *crtc,
 			       struct exynos_drm_plane *plane)
 {
+	struct exynos_drm_plane_state *state =
+				to_exynos_plane_state(plane->base.state);
 	struct decon_context *ctx = crtc->ctx;
-	struct drm_plane_state *state = plane->base.state;
-	struct drm_framebuffer *fb = state->fb;
+	struct drm_framebuffer *fb = state->base.fb;
 	int padding;
 	unsigned long val, alpha;
 	unsigned int last_x;
@@ -429,22 +430,22 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 	writel(fb->height, ctx->regs + VIDW_WHOLE_Y(win));
 
 	/* offset from the start of the buffer to read */
-	writel(plane->src_x, ctx->regs + VIDW_OFFSET_X(win));
-	writel(plane->src_y, ctx->regs + VIDW_OFFSET_Y(win));
+	writel(state->src.x, ctx->regs + VIDW_OFFSET_X(win));
+	writel(state->src.y, ctx->regs + VIDW_OFFSET_Y(win));
 
 	DRM_DEBUG_KMS("start addr = 0x%lx\n",
 			(unsigned long)val);
 	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
-			plane->crtc_w, plane->crtc_h);
+			state->crtc.w, state->crtc.h);
 
-	val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
-		VIDOSDxA_TOPLEFT_Y(plane->crtc_y);
+	val = VIDOSDxA_TOPLEFT_X(state->crtc.x) |
+		VIDOSDxA_TOPLEFT_Y(state->crtc.y);
 	writel(val, ctx->regs + VIDOSD_A(win));
 
-	last_x = plane->crtc_x + plane->crtc_w;
+	last_x = state->crtc.x + state->crtc.w;
 	if (last_x)
 		last_x--;
-	last_y = plane->crtc_y + plane->crtc_h;
+	last_y = state->crtc.y + state->crtc.h;
 	if (last_y)
 		last_y--;
 
@@ -453,7 +454,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 	writel(val, ctx->regs + VIDOSD_B(win));
 
 	DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
-			plane->crtc_x, plane->crtc_y, last_x, last_y);
+			state->crtc.x, state->crtc.y, last_x, last_y);
 
 	/* OSD alpha */
 	alpha = VIDOSDxC_ALPHA0_R_F(0x0) |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index dc41ffb26eb9..482ed2c2ed89 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -38,22 +38,44 @@ enum exynos_drm_output_type {
 	EXYNOS_DISPLAY_TYPE_VIDI,
 };
 
+struct exynos_drm_rect {
+	unsigned int x, y;
+	unsigned int w, h;
+};
+
 /*
- * Exynos drm common overlay structure.
+ * Exynos drm plane state structure.
  *
- * @base: plane object
- * @src_x: offset x on a framebuffer to be displayed.
- *	- the unit is screen coordinates.
- * @src_y: offset y on a framebuffer to be displayed.
- *	- the unit is screen coordinates.
- * @src_w: width of a partial image to be displayed from framebuffer.
- * @src_h: height of a partial image to be displayed from framebuffer.
- * @crtc_x: offset x on hardware screen.
- * @crtc_y: offset y on hardware screen.
- * @crtc_w: window width to be displayed (hardware screen).
- * @crtc_h: window height to be displayed (hardware screen).
+ * @base: plane_state object (contains drm_framebuffer pointer)
+ * @src: rectangle of the source image data to be displayed (clipped to
+ *       visible part).
+ * @crtc: rectangle of the target image position on hardware screen
+ *       (clipped to visible part).
  * @h_ratio: horizontal scaling ratio, 16.16 fixed point
  * @v_ratio: vertical scaling ratio, 16.16 fixed point
+ *
+ * this structure consists plane state data that will be applied to hardware
+ * specific overlay info.
+ */
+
+struct exynos_drm_plane_state {
+	struct drm_plane_state base;
+	struct exynos_drm_rect crtc;
+	struct exynos_drm_rect src;
+	unsigned int h_ratio;
+	unsigned int v_ratio;
+};
+
+static inline struct exynos_drm_plane_state *
+to_exynos_plane_state(struct drm_plane_state *state)
+{
+	return container_of(state, struct exynos_drm_plane_state, base);
+}
+
+/*
+ * Exynos drm common overlay structure.
+ *
+ * @base: plane object
  * @zpos: order of overlay layer(z position).
  *
  * this structure is common to exynos SoC and its contents would be copied
@@ -62,16 +84,6 @@ enum exynos_drm_output_type {
 
 struct exynos_drm_plane {
 	struct drm_plane base;
-	unsigned int src_x;
-	unsigned int src_y;
-	unsigned int src_w;
-	unsigned int src_h;
-	unsigned int crtc_x;
-	unsigned int crtc_y;
-	unsigned int crtc_w;
-	unsigned int crtc_h;
-	unsigned int h_ratio;
-	unsigned int v_ratio;
 	unsigned int zpos;
 	struct drm_framebuffer *pending_fb;
 };
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index ffcc498f5afe..739544871589 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -641,9 +641,10 @@ static void fimd_atomic_flush(struct exynos_drm_crtc *crtc,
 static void fimd_update_plane(struct exynos_drm_crtc *crtc,
 			      struct exynos_drm_plane *plane)
 {
+	struct exynos_drm_plane_state *state =
+				to_exynos_plane_state(plane->base.state);
 	struct fimd_context *ctx = crtc->ctx;
-	struct drm_plane_state *state = plane->base.state;
-	struct drm_framebuffer *fb = state->fb;
+	struct drm_framebuffer *fb = state->base.fb;
 	dma_addr_t dma_addr;
 	unsigned long val, size, offset;
 	unsigned int last_x, last_y, buf_offsize, line_size;
@@ -654,8 +655,8 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
 	if (ctx->suspended)
 		return;
 
-	offset = plane->src_x * bpp;
-	offset += plane->src_y * pitch;
+	offset = state->src.x * bpp;
+	offset += state->src.y * pitch;
 
 	/* buffer start address */
 	dma_addr = exynos_drm_fb_dma_addr(fb, 0) + offset;
@@ -663,18 +664,18 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
 	writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
 
 	/* buffer end address */
-	size = pitch * plane->crtc_h;
+	size = pitch * state->crtc.h;
 	val = (unsigned long)(dma_addr + size);
 	writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
 
 	DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
 			(unsigned long)dma_addr, val, size);
 	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
-			plane->crtc_w, plane->crtc_h);
+			state->crtc.w, state->crtc.h);
 
 	/* buffer size */
-	buf_offsize = pitch - (plane->crtc_w * bpp);
-	line_size = plane->crtc_w * bpp;
+	buf_offsize = pitch - (state->crtc.w * bpp);
+	line_size = state->crtc.w * bpp;
 	val = VIDW_BUF_SIZE_OFFSET(buf_offsize) |
 		VIDW_BUF_SIZE_PAGEWIDTH(line_size) |
 		VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
@@ -682,16 +683,16 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
 	writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
 
 	/* OSD position */
-	val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
-		VIDOSDxA_TOPLEFT_Y(plane->crtc_y) |
-		VIDOSDxA_TOPLEFT_X_E(plane->crtc_x) |
-		VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y);
+	val = VIDOSDxA_TOPLEFT_X(state->crtc.x) |
+		VIDOSDxA_TOPLEFT_Y(state->crtc.y) |
+		VIDOSDxA_TOPLEFT_X_E(state->crtc.x) |
+		VIDOSDxA_TOPLEFT_Y_E(state->crtc.y);
 	writel(val, ctx->regs + VIDOSD_A(win));
 
-	last_x = plane->crtc_x + plane->crtc_w;
+	last_x = state->crtc.x + state->crtc.w;
 	if (last_x)
 		last_x--;
-	last_y = plane->crtc_y + plane->crtc_h;
+	last_y = state->crtc.y + state->crtc.h;
 	if (last_y)
 		last_y--;
 
@@ -701,14 +702,14 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
 	writel(val, ctx->regs + VIDOSD_B(win));
 
 	DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
-			plane->crtc_x, plane->crtc_y, last_x, last_y);
+			state->crtc.x, state->crtc.y, last_x, last_y);
 
 	/* OSD size */
 	if (win != 3 && win != 4) {
 		u32 offset = VIDOSD_D(win);
 		if (win == 0)
 			offset = VIDOSD_C(win);
-		val = plane->crtc_w * plane->crtc_h;
+		val = state->crtc.w * state->crtc.h;
 		writel(val, ctx->regs + offset);
 
 		DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index c725409421b8..365a738042e2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -56,19 +56,35 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last)
 	return size;
 }
 
-static void exynos_plane_mode_set(struct drm_plane *plane,
-				  struct drm_crtc *crtc,
-				  struct drm_framebuffer *fb,
-				  int crtc_x, int crtc_y,
-				  unsigned int crtc_w, unsigned int crtc_h,
-				  uint32_t src_x, uint32_t src_y,
-				  uint32_t src_w, uint32_t src_h)
+static void exynos_plane_mode_set(struct exynos_drm_plane_state *exynos_state)
+
 {
-	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
+	struct drm_plane_state *state = &exynos_state->base;
+	struct drm_crtc *crtc = exynos_state->base.crtc;
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	int crtc_x, crtc_y;
+	unsigned int crtc_w, crtc_h;
+	unsigned int src_x, src_y;
+	unsigned int src_w, src_h;
 	unsigned int actual_w;
 	unsigned int actual_h;
 
+	/*
+	 * The original src/dest coordinates are stored in exynos_state->base,
+	 * but we want to keep another copy internal to our driver that we can
+	 * clip/modify ourselves.
+	 */
+
+	crtc_x = state->crtc_x;
+	crtc_y = state->crtc_y;
+	crtc_w = state->crtc_w;
+	crtc_h = state->crtc_h;
+
+	src_x = state->src_x >> 16;
+	src_y = state->src_y >> 16;
+	src_w = state->src_w >> 16;
+	src_h = state->src_h >> 16;
+
 	actual_w = exynos_plane_get_size(crtc_x, crtc_w, mode->hdisplay);
 	actual_h = exynos_plane_get_size(crtc_y, crtc_h, mode->vdisplay);
 
@@ -85,46 +101,93 @@ static void exynos_plane_mode_set(struct drm_plane *plane,
 	}
 
 	/* set ratio */
-	exynos_plane->h_ratio = (src_w << 16) / crtc_w;
-	exynos_plane->v_ratio = (src_h << 16) / crtc_h;
+	exynos_state->h_ratio = (src_w << 16) / crtc_w;
+	exynos_state->v_ratio = (src_h << 16) / crtc_h;
 
 	/* set drm framebuffer data. */
-	exynos_plane->src_x = src_x;
-	exynos_plane->src_y = src_y;
-	exynos_plane->src_w = (actual_w * exynos_plane->h_ratio) >> 16;
-	exynos_plane->src_h = (actual_h * exynos_plane->v_ratio) >> 16;
+	exynos_state->src.x = src_x;
+	exynos_state->src.y = src_y;
+	exynos_state->src.w = (actual_w * exynos_state->h_ratio) >> 16;
+	exynos_state->src.h = (actual_h * exynos_state->v_ratio) >> 16;
 
 	/* set plane range to be displayed. */
-	exynos_plane->crtc_x = crtc_x;
-	exynos_plane->crtc_y = crtc_y;
-	exynos_plane->crtc_w = actual_w;
-	exynos_plane->crtc_h = actual_h;
+	exynos_state->crtc.x = crtc_x;
+	exynos_state->crtc.y = crtc_y;
+	exynos_state->crtc.w = actual_w;
+	exynos_state->crtc.h = actual_h;
 
 	DRM_DEBUG_KMS("plane : offset_x/y(%d,%d), width/height(%d,%d)",
-			exynos_plane->crtc_x, exynos_plane->crtc_y,
-			exynos_plane->crtc_w, exynos_plane->crtc_h);
+			exynos_state->crtc.x, exynos_state->crtc.y,
+			exynos_state->crtc.w, exynos_state->crtc.h);
+}
 
-	plane->crtc = crtc;
+static void exynos_drm_plane_reset(struct drm_plane *plane)
+{
+	struct exynos_drm_plane_state *exynos_state;
+
+	if (plane->state) {
+		exynos_state = to_exynos_plane_state(plane->state);
+		if (exynos_state->base.fb)
+			drm_framebuffer_unreference(exynos_state->base.fb);
+		kfree(exynos_state);
+		plane->state = NULL;
+	}
+
+	exynos_state = kzalloc(sizeof(*exynos_state), GFP_KERNEL);
+	if (exynos_state) {
+		plane->state = &exynos_state->base;
+		plane->state->plane = plane;
+	}
+}
+
+static struct drm_plane_state *
+exynos_drm_plane_duplicate_state(struct drm_plane *plane)
+{
+	struct exynos_drm_plane_state *exynos_state;
+	struct exynos_drm_plane_state *copy;
+
+	exynos_state = to_exynos_plane_state(plane->state);
+	copy = kzalloc(sizeof(*exynos_state), GFP_KERNEL);
+	if (!copy)
+		return NULL;
+
+	__drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
+	return &copy->base;
+}
+
+static void exynos_drm_plane_destroy_state(struct drm_plane *plane,
+					   struct drm_plane_state *old_state)
+{
+	struct exynos_drm_plane_state *old_exynos_state =
+					to_exynos_plane_state(old_state);
+	__drm_atomic_helper_plane_destroy_state(plane, old_state);
+	kfree(old_exynos_state);
 }
 
 static struct drm_plane_funcs exynos_plane_funcs = {
 	.update_plane	= drm_atomic_helper_update_plane,
 	.disable_plane	= drm_atomic_helper_disable_plane,
 	.destroy	= drm_plane_cleanup,
-	.reset = drm_atomic_helper_plane_reset,
-	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+	.reset		= exynos_drm_plane_reset,
+	.atomic_duplicate_state = exynos_drm_plane_duplicate_state,
+	.atomic_destroy_state = exynos_drm_plane_destroy_state,
 };
 
 static int exynos_plane_atomic_check(struct drm_plane *plane,
 				     struct drm_plane_state *state)
 {
 	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
+	struct exynos_drm_plane_state *exynos_state =
+						to_exynos_plane_state(state);
+	int ret = 0;
 
-	if (!state->fb)
+	if (!state->crtc || !state->fb)
 		return 0;
 
-	return 0;
+	/* translate state into exynos_state */
+	exynos_plane_mode_set(exynos_state);
+
+	return ret;
 }
 
 static void exynos_plane_atomic_update(struct drm_plane *plane,
@@ -137,12 +200,7 @@ static void exynos_plane_atomic_update(struct drm_plane *plane,
 	if (!state->crtc)
 		return;
 
-	exynos_plane_mode_set(plane, state->crtc, state->fb,
-			      state->crtc_x, state->crtc_y,
-			      state->crtc_w, state->crtc_h,
-			      state->src_x >> 16, state->src_y >> 16,
-			      state->src_w >> 16, state->src_h >> 16);
-
+	plane->crtc = state->crtc;
 	exynos_plane->pending_fb = state->fb;
 
 	if (exynos_crtc->ops->update_plane)
@@ -159,8 +217,7 @@ static void exynos_plane_atomic_disable(struct drm_plane *plane,
 		return;
 
 	if (exynos_crtc->ops->disable_plane)
-		exynos_crtc->ops->disable_plane(exynos_crtc,
-						exynos_plane);
+		exynos_crtc->ops->disable_plane(exynos_crtc, exynos_plane);
 }
 
 static const struct drm_plane_helper_funcs plane_helper_funcs = {
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index f40de82848dc..154537a23c90 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -400,10 +400,11 @@ static void mixer_stop(struct mixer_context *ctx)
 static void vp_video_buffer(struct mixer_context *ctx,
 			    struct exynos_drm_plane *plane)
 {
+	struct exynos_drm_plane_state *state =
+				to_exynos_plane_state(plane->base.state);
 	struct mixer_resources *res = &ctx->mixer_res;
-	struct drm_plane_state *state = plane->base.state;
-	struct drm_framebuffer *fb = state->fb;
-	struct drm_display_mode *mode = &state->crtc->mode;
+	struct drm_framebuffer *fb = state->base.fb;
+	struct drm_display_mode *mode = &state->base.crtc->mode;
 	unsigned long flags;
 	dma_addr_t luma_addr[2], chroma_addr[2];
 	bool tiled_mode = false;
@@ -460,24 +461,24 @@ static void vp_video_buffer(struct mixer_context *ctx,
 	vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) |
 		VP_IMG_VSIZE(fb->height / 2));
 
-	vp_reg_write(res, VP_SRC_WIDTH, plane->src_w);
-	vp_reg_write(res, VP_SRC_HEIGHT, plane->src_h);
+	vp_reg_write(res, VP_SRC_WIDTH, state->src.w);
+	vp_reg_write(res, VP_SRC_HEIGHT, state->src.h);
 	vp_reg_write(res, VP_SRC_H_POSITION,
-			VP_SRC_H_POSITION_VAL(plane->src_x));
-	vp_reg_write(res, VP_SRC_V_POSITION, plane->src_y);
+			VP_SRC_H_POSITION_VAL(state->src.x));
+	vp_reg_write(res, VP_SRC_V_POSITION, state->src.y);
 
-	vp_reg_write(res, VP_DST_WIDTH, plane->crtc_w);
-	vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
+	vp_reg_write(res, VP_DST_WIDTH, state->crtc.w);
+	vp_reg_write(res, VP_DST_H_POSITION, state->crtc.x);
 	if (ctx->interlace) {
-		vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_h / 2);
-		vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
+		vp_reg_write(res, VP_DST_HEIGHT, state->crtc.h / 2);
+		vp_reg_write(res, VP_DST_V_POSITION, state->crtc.y / 2);
 	} else {
-		vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_h);
-		vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
+		vp_reg_write(res, VP_DST_HEIGHT, state->crtc.h);
+		vp_reg_write(res, VP_DST_V_POSITION, state->crtc.y);
 	}
 
-	vp_reg_write(res, VP_H_RATIO, plane->h_ratio);
-	vp_reg_write(res, VP_V_RATIO, plane->v_ratio);
+	vp_reg_write(res, VP_H_RATIO, state->h_ratio);
+	vp_reg_write(res, VP_V_RATIO, state->v_ratio);
 
 	vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
 
@@ -509,15 +510,18 @@ static void mixer_layer_update(struct mixer_context *ctx)
 static int mixer_setup_scale(const struct exynos_drm_plane *plane,
 		unsigned int *x_ratio, unsigned int *y_ratio)
 {
-	if (plane->crtc_w != plane->src_w) {
-		if (plane->crtc_w == 2 * plane->src_w)
+	struct exynos_drm_plane_state *state =
+				to_exynos_plane_state(plane->base.state);
+
+	if (state->crtc.w != state->src.w) {
+		if (state->crtc.w == 2 * state->src.w)
 			*x_ratio = 1;
 		else
 			goto fail;
 	}
 
-	if (plane->crtc_h != plane->src_h) {
-		if (plane->crtc_h == 2 * plane->src_h)
+	if (state->crtc.h != state->src.h) {
+		if (state->crtc.h == 2 * state->src.h)
 			*y_ratio = 1;
 		else
 			goto fail;
@@ -533,10 +537,11 @@ fail:
 static void mixer_graph_buffer(struct mixer_context *ctx,
 			       struct exynos_drm_plane *plane)
 {
+	struct exynos_drm_plane_state *state =
+				to_exynos_plane_state(plane->base.state);
 	struct mixer_resources *res = &ctx->mixer_res;
-	struct drm_plane_state *state = plane->base.state;
-	struct drm_framebuffer *fb = state->fb;
-	struct drm_display_mode *mode = &state->crtc->mode;
+	struct drm_framebuffer *fb = state->base.fb;
+	struct drm_display_mode *mode = &state->base.crtc->mode;
 	unsigned long flags;
 	unsigned int win = plane->zpos;
 	unsigned int x_ratio = 0, y_ratio = 0;
@@ -572,13 +577,13 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
 	if (mixer_setup_scale(plane, &x_ratio, &y_ratio))
 		return;
 
-	dst_x_offset = plane->crtc_x;
-	dst_y_offset = plane->crtc_y;
+	dst_x_offset = state->crtc.x;
+	dst_y_offset = state->crtc.y;
 
 	/* converting dma address base and source offset */
 	dma_addr = exynos_drm_fb_dma_addr(fb, 0)
-		+ (plane->src_x * fb->bits_per_pixel >> 3)
-		+ (plane->src_y * fb->pitches[0]);
+		+ (state->src.x * fb->bits_per_pixel >> 3)
+		+ (state->src.y * fb->pitches[0]);
 	src_x_offset = 0;
 	src_y_offset = 0;
 
@@ -606,8 +611,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
 		mixer_reg_write(res, MXR_RESOLUTION, val);
 	}
 
-	val  = MXR_GRP_WH_WIDTH(plane->src_w);
-	val |= MXR_GRP_WH_HEIGHT(plane->src_h);
+	val  = MXR_GRP_WH_WIDTH(state->src.w);
+	val |= MXR_GRP_WH_HEIGHT(state->src.h);
 	val |= MXR_GRP_WH_H_SCALE(x_ratio);
 	val |= MXR_GRP_WH_V_SCALE(y_ratio);
 	mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
-- 
1.9.2

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

* [PATCH v2 08/22] drm/exynos: mixer: use crtc->state->adjusted_mode instead of crtc->mode
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (6 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 07/22] drm/exynos: introduce exynos_drm_plane_state structure Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 09/22] drm/exynos: mixer: enable video overlay plane only when VP is available Marek Szyprowski
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Javier Martinez Canillas, Krzysztof Kozlowski,
	Bartlomiej Zolnierkiewicz, Seung-Woo Kim, Andrzej Hajda,
	Tobias Jakobi, Marek Szyprowski

This patch replaces usage of crtc->mode with crtc->state->adjusted_mode
like it is already done in common plane code.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_mixer.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 154537a23c90..84ee3396c429 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -402,9 +402,9 @@ static void vp_video_buffer(struct mixer_context *ctx,
 {
 	struct exynos_drm_plane_state *state =
 				to_exynos_plane_state(plane->base.state);
+	struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode;
 	struct mixer_resources *res = &ctx->mixer_res;
 	struct drm_framebuffer *fb = state->base.fb;
-	struct drm_display_mode *mode = &state->base.crtc->mode;
 	unsigned long flags;
 	dma_addr_t luma_addr[2], chroma_addr[2];
 	bool tiled_mode = false;
@@ -539,9 +539,9 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
 {
 	struct exynos_drm_plane_state *state =
 				to_exynos_plane_state(plane->base.state);
+	struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode;
 	struct mixer_resources *res = &ctx->mixer_res;
 	struct drm_framebuffer *fb = state->base.fb;
-	struct drm_display_mode *mode = &state->base.crtc->mode;
 	unsigned long flags;
 	unsigned int win = plane->zpos;
 	unsigned int x_ratio = 0, y_ratio = 0;
-- 
1.9.2

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

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

* [PATCH v2 09/22] drm/exynos: mixer: enable video overlay plane only when VP is available
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (7 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 08/22] drm/exynos: mixer: use crtc->state->adjusted_mode instead of crtc->mode Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 10/22] drm/exynos: introduce exynos_drm_plane_config structure Marek Szyprowski
                   ` (13 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

Video overlay plane should be registered only when suitable hardware
sub-block (Video Processor) is available.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_mixer.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 84ee3396c429..8d2ce13eb725 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -1167,6 +1167,9 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
 		const uint32_t *formats;
 		unsigned int fcount;
 
+		if (zpos == VP_DEFAULT_WIN && !ctx->vp_enabled)
+			continue;
+
 		if (zpos < VP_DEFAULT_WIN) {
 			formats = mixer_formats;
 			fcount = ARRAY_SIZE(mixer_formats);
-- 
1.9.2

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

* [PATCH v2 10/22] drm/exynos: introduce exynos_drm_plane_config structure
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (8 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 09/22] drm/exynos: mixer: enable video overlay plane only when VP is available Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-12-10 11:47   ` Inki Dae
  2015-11-30 13:53 ` [PATCH v2 11/22] drm/exynos: add generic check for plane state Marek Szyprowski
                   ` (12 subsequent siblings)
  22 siblings, 1 reply; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

This patch adds common structure for keeping plane configuration and
capabilities data. This patch is inspired by similar code developed by
Tobias Jakobi.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 18 ++++++++---
 drivers/gpu/drm/exynos/exynos7_drm_decon.c    | 23 +++++++++-----
 drivers/gpu/drm/exynos/exynos_drm_drv.h       | 19 ++++++++++++
 drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 25 ++++++++++-----
 drivers/gpu/drm/exynos/exynos_drm_plane.c     | 34 +++++++++------------
 drivers/gpu/drm/exynos/exynos_drm_plane.h     |  7 ++---
 drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 25 ++++++++++-----
 drivers/gpu/drm/exynos/exynos_mixer.c         | 44 +++++++++++++++------------
 8 files changed, 121 insertions(+), 74 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 12f558fc3ef6..189ee5ca0a7a 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -26,7 +26,6 @@
 #include "exynos_drm_iommu.h"
 
 #define WINDOWS_NR	3
-#define CURSOR_WIN	2
 #define MIN_FB_WIDTH_FOR_16WORD_BURST	128
 
 static const char * const decon_clks_name[] = {
@@ -57,6 +56,7 @@ struct decon_context {
 	struct drm_device		*drm_dev;
 	struct exynos_drm_crtc		*crtc;
 	struct exynos_drm_plane		planes[WINDOWS_NR];
+	struct exynos_drm_plane_config	configs[WINDOWS_NR];
 	void __iomem			*addr;
 	struct clk			*clks[ARRAY_SIZE(decon_clks_name)];
 	int				pipe;
@@ -72,6 +72,12 @@ static const uint32_t decon_formats[] = {
 	DRM_FORMAT_ARGB8888,
 };
 
+static const enum drm_plane_type decon_win_types[WINDOWS_NR] = {
+	DRM_PLANE_TYPE_PRIMARY,
+	DRM_PLANE_TYPE_OVERLAY,
+	DRM_PLANE_TYPE_CURSOR,
+};
+
 static inline void decon_set_bits(struct decon_context *ctx, u32 reg, u32 mask,
 				  u32 val)
 {
@@ -484,7 +490,6 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
 	struct exynos_drm_private *priv = drm_dev->dev_private;
 	struct exynos_drm_plane *exynos_plane;
 	enum exynos_drm_output_type out_type;
-	enum drm_plane_type type;
 	unsigned int win;
 	int ret;
 
@@ -494,10 +499,13 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
 	for (win = ctx->first_win; win < WINDOWS_NR; win++) {
 		int tmp = (win == ctx->first_win) ? 0 : win;
 
-		type = exynos_plane_get_type(tmp, CURSOR_WIN);
+		ctx->configs[win].pixel_formats = decon_formats;
+		ctx->configs[win].num_pixel_formats = ARRAY_SIZE(decon_formats);
+		ctx->configs[win].zpos = win;
+		ctx->configs[win].type = decon_win_types[tmp];
+
 		ret = exynos_plane_init(drm_dev, &ctx->planes[win],
-				1 << ctx->pipe, type, decon_formats,
-				ARRAY_SIZE(decon_formats), win);
+					1 << ctx->pipe, &ctx->configs[win]);
 		if (ret)
 			return ret;
 	}
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 1c62de1a0839..c47f9af8170b 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -41,13 +41,13 @@
 #define MIN_FB_WIDTH_FOR_16WORD_BURST 128
 
 #define WINDOWS_NR	2
-#define CURSOR_WIN	1
 
 struct decon_context {
 	struct device			*dev;
 	struct drm_device		*drm_dev;
 	struct exynos_drm_crtc		*crtc;
 	struct exynos_drm_plane		planes[WINDOWS_NR];
+	struct exynos_drm_plane_config	configs[WINDOWS_NR];
 	struct clk			*pclk;
 	struct clk			*aclk;
 	struct clk			*eclk;
@@ -82,6 +82,11 @@ static const uint32_t decon_formats[] = {
 	DRM_FORMAT_BGRA8888,
 };
 
+static const enum drm_plane_type decon_win_types[WINDOWS_NR] = {
+	DRM_PLANE_TYPE_PRIMARY,
+	DRM_PLANE_TYPE_CURSOR,
+};
+
 static void decon_wait_for_vblank(struct exynos_drm_crtc *crtc)
 {
 	struct decon_context *ctx = crtc->ctx;
@@ -637,8 +642,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
 	struct decon_context *ctx = dev_get_drvdata(dev);
 	struct drm_device *drm_dev = data;
 	struct exynos_drm_plane *exynos_plane;
-	enum drm_plane_type type;
-	unsigned int zpos;
+	unsigned int i;
 	int ret;
 
 	ret = decon_ctx_initialize(ctx, drm_dev);
@@ -647,11 +651,14 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
 		return ret;
 	}
 
-	for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
-		type = exynos_plane_get_type(zpos, CURSOR_WIN);
-		ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
-					1 << ctx->pipe, type, decon_formats,
-					ARRAY_SIZE(decon_formats), zpos);
+	for (i = 0; i < WINDOWS_NR; i++) {
+		ctx->configs[i].pixel_formats = decon_formats;
+		ctx->configs[i].num_pixel_formats = ARRAY_SIZE(decon_formats);
+		ctx->configs[i].zpos = i;
+		ctx->configs[i].type = decon_win_types[i];
+
+		ret = exynos_plane_init(drm_dev, &ctx->planes[i],
+					1 << ctx->pipe, &ctx->configs[i]);
 		if (ret)
 			return ret;
 	}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 482ed2c2ed89..6f8a296a3115 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -84,11 +84,30 @@ to_exynos_plane_state(struct drm_plane_state *state)
 
 struct exynos_drm_plane {
 	struct drm_plane base;
+	const struct exynos_drm_plane_config *config;
 	unsigned int zpos;
 	struct drm_framebuffer *pending_fb;
 };
 
 /*
+ * Exynos DRM plane configuration structure.
+ *
+ * @zpos: z-position of the plane.
+ * @type: type of the plane (primary, cursor or overlay).
+ * @pixel_formats: supported pixel formats.
+ * @num_pixel_formats: number of elements in 'pixel_formats'.
+ * @capabilities: supported features (see EXYNOS_DRM_PLANE_CAP_*)
+ */
+
+struct exynos_drm_plane_config {
+	unsigned int zpos;
+	enum drm_plane_type type;
+	const uint32_t *pixel_formats;
+	unsigned int num_pixel_formats;
+	unsigned int capabilities;
+};
+
+/*
  * Exynos drm crtc ops
  *
  * @enable: enable the device
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 739544871589..70cd2681e343 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -88,7 +88,6 @@
 
 /* FIMD has totally five hardware windows. */
 #define WINDOWS_NR	5
-#define CURSOR_WIN	4
 
 struct fimd_driver_data {
 	unsigned int timing_base;
@@ -151,6 +150,7 @@ struct fimd_context {
 	struct drm_device		*drm_dev;
 	struct exynos_drm_crtc		*crtc;
 	struct exynos_drm_plane		planes[WINDOWS_NR];
+	struct exynos_drm_plane_config	configs[WINDOWS_NR];
 	struct clk			*bus_clk;
 	struct clk			*lcd_clk;
 	void __iomem			*regs;
@@ -188,6 +188,14 @@ static const struct of_device_id fimd_driver_dt_match[] = {
 };
 MODULE_DEVICE_TABLE(of, fimd_driver_dt_match);
 
+static const enum drm_plane_type fimd_win_types[WINDOWS_NR] = {
+	DRM_PLANE_TYPE_PRIMARY,
+	DRM_PLANE_TYPE_OVERLAY,
+	DRM_PLANE_TYPE_OVERLAY,
+	DRM_PLANE_TYPE_OVERLAY,
+	DRM_PLANE_TYPE_CURSOR,
+};
+
 static const uint32_t fimd_formats[] = {
 	DRM_FORMAT_C8,
 	DRM_FORMAT_XRGB1555,
@@ -927,18 +935,19 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
 	struct drm_device *drm_dev = data;
 	struct exynos_drm_private *priv = drm_dev->dev_private;
 	struct exynos_drm_plane *exynos_plane;
-	enum drm_plane_type type;
-	unsigned int zpos;
+	unsigned int i;
 	int ret;
 
 	ctx->drm_dev = drm_dev;
 	ctx->pipe = priv->pipe++;
 
-	for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
-		type = exynos_plane_get_type(zpos, CURSOR_WIN);
-		ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
-					1 << ctx->pipe, type, fimd_formats,
-					ARRAY_SIZE(fimd_formats), zpos);
+	for (i = 0; i < WINDOWS_NR; i++) {
+		ctx->configs[i].pixel_formats = fimd_formats;
+		ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_formats);
+		ctx->configs[i].zpos = i;
+		ctx->configs[i].type = fimd_win_types[i];
+		ret = exynos_plane_init(drm_dev, &ctx->planes[i],
+					1 << ctx->pipe, &ctx->configs[i]);
 		if (ret)
 			return ret;
 	}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 365a738042e2..b620d7a76799 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -246,28 +246,20 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane,
 	drm_object_attach_property(&plane->base, prop, zpos);
 }
 
-enum drm_plane_type exynos_plane_get_type(unsigned int zpos,
-					  unsigned int cursor_win)
-{
-		if (zpos == DEFAULT_WIN)
-			return DRM_PLANE_TYPE_PRIMARY;
-		else if (zpos == cursor_win)
-			return DRM_PLANE_TYPE_CURSOR;
-		else
-			return DRM_PLANE_TYPE_OVERLAY;
-}
-
 int exynos_plane_init(struct drm_device *dev,
 		      struct exynos_drm_plane *exynos_plane,
-		      unsigned long possible_crtcs, enum drm_plane_type type,
-		      const uint32_t *formats, unsigned int fcount,
-		      unsigned int zpos)
+		      unsigned long possible_crtcs,
+		      const struct exynos_drm_plane_config *config)
 {
 	int err;
 
-	err = drm_universal_plane_init(dev, &exynos_plane->base, possible_crtcs,
-				       &exynos_plane_funcs, formats, fcount,
-				       type);
+	err = drm_universal_plane_init(dev, &exynos_plane->base,
+				       possible_crtcs,
+				       &exynos_plane_funcs,
+				       config->pixel_formats,
+				       config->num_pixel_formats,
+				       config->type);
+
 	if (err) {
 		DRM_ERROR("failed to initialize plane\n");
 		return err;
@@ -275,10 +267,12 @@ int exynos_plane_init(struct drm_device *dev,
 
 	drm_plane_helper_add(&exynos_plane->base, &plane_helper_funcs);
 
-	exynos_plane->zpos = zpos;
+	exynos_plane->zpos = config->zpos;
+	exynos_plane->config = config;
 
-	if (type == DRM_PLANE_TYPE_OVERLAY)
-		exynos_plane_attach_zpos_property(&exynos_plane->base, zpos);
+	if (config->type == DRM_PLANE_TYPE_OVERLAY)
+		exynos_plane_attach_zpos_property(&exynos_plane->base,
+						  config->zpos);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index abb641e64c23..0dd096548284 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -9,10 +9,7 @@
  *
  */
 
-enum drm_plane_type exynos_plane_get_type(unsigned int zpos,
-					  unsigned int cursor_win);
 int exynos_plane_init(struct drm_device *dev,
 		      struct exynos_drm_plane *exynos_plane,
-		      unsigned long possible_crtcs, enum drm_plane_type type,
-		      const uint32_t *formats, unsigned int fcount,
-		      unsigned int zpos);
+		      unsigned long possible_crtcs,
+		      const struct exynos_drm_plane_config *config);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 3ce141236fad..90701647aef1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -30,7 +30,6 @@
 
 /* vidi has totally three virtual windows. */
 #define WINDOWS_NR		3
-#define CURSOR_WIN		2
 
 #define ctx_from_connector(c)	container_of(c, struct vidi_context, \
 					connector)
@@ -90,6 +89,12 @@ static const uint32_t formats[] = {
 	DRM_FORMAT_NV12,
 };
 
+static const enum drm_plane_type vidi_win_types[WINDOWS_NR] = {
+	DRM_PLANE_TYPE_PRIMARY,
+	DRM_PLANE_TYPE_OVERLAY,
+	DRM_PLANE_TYPE_CURSOR,
+};
+
 static int vidi_enable_vblank(struct exynos_drm_crtc *crtc)
 {
 	struct vidi_context *ctx = crtc->ctx;
@@ -442,17 +447,21 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
 	struct drm_device *drm_dev = data;
 	struct drm_encoder *encoder = &ctx->encoder;
 	struct exynos_drm_plane *exynos_plane;
-	enum drm_plane_type type;
-	unsigned int zpos;
+	struct exynos_drm_plane_config plane_config = { 0 };
+	unsigned int i;
 	int pipe, ret;
 
 	vidi_ctx_initialize(ctx, drm_dev);
 
-	for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
-		type = exynos_plane_get_type(zpos, CURSOR_WIN);
-		ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
-					1 << ctx->pipe, type, formats,
-					ARRAY_SIZE(formats), zpos);
+	plane_config.pixel_formats = formats;
+	plane_config.num_pixel_formats = ARRAY_SIZE(formats);
+
+	for (i = 0; i < WINDOWS_NR; i++) {
+		plane_config.zpos = i;
+		plane_config.type = vidi_win_types(i);
+
+		ret = exynos_plane_init(drm_dev, &ctx->planes[i],
+					1 << ctx->pipe, &plane_config);
 		if (ret)
 			return ret;
 	}
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 8d2ce13eb725..a229f86d221a 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -43,7 +43,6 @@
 
 #define MIXER_WIN_NR		3
 #define VP_DEFAULT_WIN		2
-#define CURSOR_WIN		1
 
 /* The pixelformats that are natively supported by the mixer. */
 #define MXR_FORMAT_RGB565	4
@@ -112,6 +111,25 @@ struct mixer_drv_data {
 	bool					has_sclk;
 };
 
+static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
+	{
+		.zpos = 0,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.pixel_formats = mixer_formats,
+		.num_pixel_formats = ARRAY_SIZE(mixer_formats),
+	}, {
+		.zpos = 1,
+		.type = DRM_PLANE_TYPE_CURSOR,
+		.pixel_formats = mixer_formats,
+		.num_pixel_formats = ARRAY_SIZE(mixer_formats),
+	}, {
+		.zpos = 2,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.pixel_formats = vp_formats,
+		.num_pixel_formats = ARRAY_SIZE(vp_formats),
+	},
+};
+
 static const u8 filter_y_horiz_tap8[] = {
 	0,	-1,	-1,	-1,	-1,	-1,	-1,	-1,
 	-1,	-1,	-1,	-1,	-1,	0,	0,	0,
@@ -1155,33 +1173,19 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
 	struct mixer_context *ctx = dev_get_drvdata(dev);
 	struct drm_device *drm_dev = data;
 	struct exynos_drm_plane *exynos_plane;
-	unsigned int zpos;
+	unsigned int i;
 	int ret;
 
 	ret = mixer_initialize(ctx, drm_dev);
 	if (ret)
 		return ret;
 
-	for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) {
-		enum drm_plane_type type;
-		const uint32_t *formats;
-		unsigned int fcount;
-
-		if (zpos == VP_DEFAULT_WIN && !ctx->vp_enabled)
+	for (i = 0; i < MIXER_WIN_NR; i++) {
+		if (i == VP_DEFAULT_WIN && !ctx->vp_enabled)
 			continue;
 
-		if (zpos < VP_DEFAULT_WIN) {
-			formats = mixer_formats;
-			fcount = ARRAY_SIZE(mixer_formats);
-		} else {
-			formats = vp_formats;
-			fcount = ARRAY_SIZE(vp_formats);
-		}
-
-		type = exynos_plane_get_type(zpos, CURSOR_WIN);
-		ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
-					1 << ctx->pipe, type, formats, fcount,
-					zpos);
+		ret = exynos_plane_init(drm_dev, &ctx->planes[i],
+					1 << ctx->pipe, &plane_configs[i]);
 		if (ret)
 			return ret;
 	}
-- 
1.9.2

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

* [PATCH v2 11/22] drm/exynos: add generic check for plane state
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (9 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 10/22] drm/exynos: introduce exynos_drm_plane_config structure Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 12/22] drm/exynos: mixer: use ratio precalculated in exynos_state Marek Szyprowski
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

This patch adds generic check for plane state - display area dimensions,
so drivers can always assume that they get valid plane state to set.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_drv.h   |  3 +++
 drivers/gpu/drm/exynos/exynos_drm_plane.c | 31 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/exynos/exynos_mixer.c     |  3 +++
 3 files changed, 37 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 6f8a296a3115..82bbd7f4b316 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -89,6 +89,9 @@ struct exynos_drm_plane {
 	struct drm_framebuffer *pending_fb;
 };
 
+#define EXYNOS_DRM_PLANE_CAP_DOUBLE	(1 << 0)
+#define EXYNOS_DRM_PLANE_CAP_SCALE	(1 << 1)
+
 /*
  * Exynos DRM plane configuration structure.
  *
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index b620d7a76799..9eaa8627175f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -173,6 +173,36 @@ static struct drm_plane_funcs exynos_plane_funcs = {
 	.atomic_destroy_state = exynos_drm_plane_destroy_state,
 };
 
+static int
+exynos_drm_plane_check_size(const struct exynos_drm_plane_config *config,
+			    struct exynos_drm_plane_state *state)
+{
+	bool width_ok = false, height_ok = false;
+
+	if (config->capabilities & EXYNOS_DRM_PLANE_CAP_SCALE)
+		return 0;
+
+	if (state->src.w == state->crtc.w)
+		width_ok = true;
+
+	if (state->src.h == state->crtc.h)
+		height_ok = true;
+
+	if ((config->capabilities & EXYNOS_DRM_PLANE_CAP_DOUBLE) &&
+	    state->h_ratio == (1 << 15))
+		width_ok = true;
+
+	if ((config->capabilities & EXYNOS_DRM_PLANE_CAP_DOUBLE) &&
+	    state->v_ratio == (1 << 15))
+		height_ok = true;
+
+	if (width_ok & height_ok)
+		return 0;
+
+	DRM_DEBUG_KMS("scaling mode is not supported");
+	return -ENOTSUPP;
+}
+
 static int exynos_plane_atomic_check(struct drm_plane *plane,
 				     struct drm_plane_state *state)
 {
@@ -187,6 +217,7 @@ static int exynos_plane_atomic_check(struct drm_plane *plane,
 	/* translate state into exynos_state */
 	exynos_plane_mode_set(exynos_state);
 
+	ret = exynos_drm_plane_check_size(exynos_plane->config, exynos_state);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index a229f86d221a..4190285798ef 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -117,16 +117,19 @@ static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
 		.type = DRM_PLANE_TYPE_PRIMARY,
 		.pixel_formats = mixer_formats,
 		.num_pixel_formats = ARRAY_SIZE(mixer_formats),
+		.capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE,
 	}, {
 		.zpos = 1,
 		.type = DRM_PLANE_TYPE_CURSOR,
 		.pixel_formats = mixer_formats,
 		.num_pixel_formats = ARRAY_SIZE(mixer_formats),
+		.capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE,
 	}, {
 		.zpos = 2,
 		.type = DRM_PLANE_TYPE_OVERLAY,
 		.pixel_formats = vp_formats,
 		.num_pixel_formats = ARRAY_SIZE(vp_formats),
+		.capabilities = EXYNOS_DRM_PLANE_CAP_SCALE,
 	},
 };
 
-- 
1.9.2

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

* [PATCH v2 12/22] drm/exynos: mixer: use ratio precalculated in exynos_state
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (10 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 11/22] drm/exynos: add generic check for plane state Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 13/22] drm/exynos: fix clipping when scaling is enabled Marek Szyprowski
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Javier Martinez Canillas, Krzysztof Kozlowski,
	Bartlomiej Zolnierkiewicz, Seung-Woo Kim, Andrzej Hajda,
	Tobias Jakobi, Marek Szyprowski

Common plane code already calculates and checks for supported scalling
modes, so additional code in mixer driver can be now removed.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_mixer.c | 33 +++------------------------------
 1 file changed, 3 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 4190285798ef..dfb35e2da4db 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -528,33 +528,6 @@ static void mixer_layer_update(struct mixer_context *ctx)
 	mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
 }
 
-static int mixer_setup_scale(const struct exynos_drm_plane *plane,
-		unsigned int *x_ratio, unsigned int *y_ratio)
-{
-	struct exynos_drm_plane_state *state =
-				to_exynos_plane_state(plane->base.state);
-
-	if (state->crtc.w != state->src.w) {
-		if (state->crtc.w == 2 * state->src.w)
-			*x_ratio = 1;
-		else
-			goto fail;
-	}
-
-	if (state->crtc.h != state->src.h) {
-		if (state->crtc.h == 2 * state->src.h)
-			*y_ratio = 1;
-		else
-			goto fail;
-	}
-
-	return 0;
-
-fail:
-	DRM_DEBUG_KMS("only 2x width/height scaling of plane supported\n");
-	return -ENOTSUPP;
-}
-
 static void mixer_graph_buffer(struct mixer_context *ctx,
 			       struct exynos_drm_plane *plane)
 {
@@ -594,9 +567,9 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
 		return;
 	}
 
-	/* check if mixer supports requested scaling setup */
-	if (mixer_setup_scale(plane, &x_ratio, &y_ratio))
-		return;
+	/* ratio is already checked by common plane code */
+	x_ratio = state->h_ratio == (1 << 15);
+	y_ratio = state->v_ratio == (1 << 15);
 
 	dst_x_offset = state->crtc.x;
 	dst_y_offset = state->crtc.y;
-- 
1.9.2

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

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

* [PATCH v2 13/22] drm/exynos: fix clipping when scaling is enabled
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (11 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 12/22] drm/exynos: mixer: use ratio precalculated in exynos_state Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 14/22] drm/exynos: fimd: fix dma burst size setting for small plane size Marek Szyprowski
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

This patch fixes calculation of src x/y offset for negative crtc x/y
values when scaling is enabled. This fixes possible IOMMU fault when
scaling is enabled.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_plane.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 9eaa8627175f..427aeec78a28 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -85,25 +85,26 @@ static void exynos_plane_mode_set(struct exynos_drm_plane_state *exynos_state)
 	src_w = state->src_w >> 16;
 	src_h = state->src_h >> 16;
 
+	/* set ratio */
+	exynos_state->h_ratio = (src_w << 16) / crtc_w;
+	exynos_state->v_ratio = (src_h << 16) / crtc_h;
+
+	/* clip to visible area */
 	actual_w = exynos_plane_get_size(crtc_x, crtc_w, mode->hdisplay);
 	actual_h = exynos_plane_get_size(crtc_y, crtc_h, mode->vdisplay);
 
 	if (crtc_x < 0) {
 		if (actual_w)
-			src_x -= crtc_x;
+			src_x += ((-crtc_x) * exynos_state->h_ratio) >> 16;
 		crtc_x = 0;
 	}
 
 	if (crtc_y < 0) {
 		if (actual_h)
-			src_y -= crtc_y;
+			src_y += ((-crtc_y) * exynos_state->v_ratio) >> 16;
 		crtc_y = 0;
 	}
 
-	/* set ratio */
-	exynos_state->h_ratio = (src_w << 16) / crtc_w;
-	exynos_state->v_ratio = (src_h << 16) / crtc_h;
-
 	/* set drm framebuffer data. */
 	exynos_state->src.x = src_x;
 	exynos_state->src.y = src_y;
-- 
1.9.2

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

* [PATCH v2 14/22] drm/exynos: fimd: fix dma burst size setting for small plane size
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (12 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 13/22] drm/exynos: fix clipping when scaling is enabled Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 15:40   ` Daniel Stone
  2015-12-10 11:35   ` Inki Dae
  2015-11-30 13:53 ` [PATCH v2 15/22] drm/exynos: gem: remove old unused prototypes Marek Szyprowski
                   ` (8 subsequent siblings)
  22 siblings, 2 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

This patch fixes trashed display of buffers cropped to very small width.
Even if DMA is unstable and causes tearing when changing the burst size,
it is still better than displaying a garbage.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_fimd.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 70cd2681e343..2e2247126581 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -487,7 +487,7 @@ static void fimd_commit(struct exynos_drm_crtc *crtc)
 
 
 static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
-				struct drm_framebuffer *fb)
+				uint32_t pixel_format, int width)
 {
 	unsigned long val;
 
@@ -498,11 +498,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
 	 * So the request format is ARGB8888 then change it to XRGB8888.
 	 */
 	if (ctx->driver_data->has_limited_fmt && !win) {
-		if (fb->pixel_format == DRM_FORMAT_ARGB8888)
-			fb->pixel_format = DRM_FORMAT_XRGB8888;
+		if (pixel_format == DRM_FORMAT_ARGB8888)
+			pixel_format = DRM_FORMAT_XRGB8888;
 	}
 
-	switch (fb->pixel_format) {
+	switch (pixel_format) {
 	case DRM_FORMAT_C8:
 		val |= WINCON0_BPPMODE_8BPP_PALETTE;
 		val |= WINCONx_BURSTLEN_8WORD;
@@ -538,17 +538,15 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
 		break;
 	}
 
-	DRM_DEBUG_KMS("bpp = %d\n", fb->bits_per_pixel);
-
 	/*
-	 * In case of exynos, setting dma-burst to 16Word causes permanent
-	 * tearing for very small buffers, e.g. cursor buffer. Burst Mode
-	 * switching which is based on plane size is not recommended as
-	 * plane size varies alot towards the end of the screen and rapid
-	 * movement causes unstable DMA which results into iommu crash/tear.
+	 * Setting dma-burst to 16Word causes permanent tearing for very small
+	 * buffers, e.g. cursor buffer. Burst Mode switching which based on
+	 * plane size is not recommended as plane size varies alot towards the
+	 * end of the screen and rapid movement causes unstable DMA, but it is
+	 * still better to change dma-burst than displaying garbage.
 	 */
 
-	if (fb->width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
+	if (width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
 		val &= ~WINCONx_BURSTLEN_MASK;
 		val |= WINCONx_BURSTLEN_4WORD;
 	}
@@ -723,7 +721,7 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
 		DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
 	}
 
-	fimd_win_set_pixfmt(ctx, win, fb);
+	fimd_win_set_pixfmt(ctx, win, fb->pixel_format, state->src.w);
 
 	/* hardware window 0 doesn't support color key. */
 	if (win != 0)
-- 
1.9.2

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

* [PATCH v2 15/22] drm/exynos: gem: remove old unused prototypes
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (13 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 14/22] drm/exynos: fimd: fix dma burst size setting for small plane size Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 16/22] drm/exynos: add fb pointer to exynos_drm_plane_state Marek Szyprowski
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

This patch removes old, unused function prototypes from exynos_drm_gem.h.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_gem.h | 28 ----------------------------
 1 file changed, 28 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
index 37ab8b282db6..9ca5047959ec 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -55,8 +55,6 @@ struct exynos_drm_gem {
 	struct sg_table		*sgt;
 };
 
-struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
-
 /* destroy a buffer with gem object */
 void exynos_drm_gem_destroy(struct exynos_drm_gem *exynos_gem);
 
@@ -91,10 +89,6 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
 					unsigned int gem_handle,
 					struct drm_file *filp);
 
-/* map user space allocated by malloc to pages. */
-int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
-				      struct drm_file *file_priv);
-
 /* get buffer information to memory region allocated by gem. */
 int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
 				      struct drm_file *file_priv);
@@ -123,28 +117,6 @@ int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 /* set vm_flags and we can change the vm attribute to other one at here. */
 int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
 
-static inline int vma_is_io(struct vm_area_struct *vma)
-{
-	return !!(vma->vm_flags & (VM_IO | VM_PFNMAP));
-}
-
-/* get a copy of a virtual memory region. */
-struct vm_area_struct *exynos_gem_get_vma(struct vm_area_struct *vma);
-
-/* release a userspace virtual memory area. */
-void exynos_gem_put_vma(struct vm_area_struct *vma);
-
-/* get pages from user space. */
-int exynos_gem_get_pages_from_userptr(unsigned long start,
-						unsigned int npages,
-						struct page **pages,
-						struct vm_area_struct *vma);
-
-/* drop the reference to pages. */
-void exynos_gem_put_pages_to_userptr(struct page **pages,
-					unsigned int npages,
-					struct vm_area_struct *vma);
-
 /* map sgt with dma region. */
 int exynos_gem_map_sgt_with_dma(struct drm_device *drm_dev,
 				struct sg_table *sgt,
-- 
1.9.2

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

* [PATCH v2 16/22] drm/exynos: add fb pointer to exynos_drm_plane_state
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (14 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 15/22] drm/exynos: gem: remove old unused prototypes Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 17/22] drm/exynos: gem: set default alignment for dumb GEM buffers Marek Szyprowski
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

Add framebuffer pointer to exynos_drm_plane_state and tell drivers to use
it. This lets common plane code to set temporary framebuffer in the
future and drivers will use it without additional changes.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 2 +-
 drivers/gpu/drm/exynos/exynos7_drm_decon.c    | 2 +-
 drivers/gpu/drm/exynos/exynos_drm_drv.h       | 8 ++++++--
 drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 2 +-
 drivers/gpu/drm/exynos/exynos_drm_plane.c     | 2 ++
 drivers/gpu/drm/exynos/exynos_mixer.c         | 4 ++--
 6 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 189ee5ca0a7a..1f705bede7dd 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -269,7 +269,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 	struct exynos_drm_plane_state *state =
 				to_exynos_plane_state(plane->base.state);
 	struct decon_context *ctx = crtc->ctx;
-	struct drm_framebuffer *fb = state->base.fb;
+	struct drm_framebuffer *fb = state->fb;
 	unsigned int win = plane->zpos;
 	unsigned int bpp = fb->bits_per_pixel >> 3;
 	unsigned int pitch = fb->pitches[0];
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index c47f9af8170b..17aa11702a40 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -402,7 +402,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 	struct exynos_drm_plane_state *state =
 				to_exynos_plane_state(plane->base.state);
 	struct decon_context *ctx = crtc->ctx;
-	struct drm_framebuffer *fb = state->base.fb;
+	struct drm_framebuffer *fb = state->fb;
 	int padding;
 	unsigned long val, alpha;
 	unsigned int last_x;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 82bbd7f4b316..bb2e449a20c3 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -53,9 +53,12 @@ struct exynos_drm_rect {
  *       (clipped to visible part).
  * @h_ratio: horizontal scaling ratio, 16.16 fixed point
  * @v_ratio: vertical scaling ratio, 16.16 fixed point
+ * @fb: framebuffer with image data to be displayed (drivers should use this
+ *      instead of .base->fb)
  *
- * this structure consists plane state data that will be applied to hardware
- * specific overlay info.
+ * This structure consists plane state data that will be applied to hardware
+ * specific overlay info. Some data is duplicated (comparing with base state)
+ * to let common code to modify it for internal use.
  */
 
 struct exynos_drm_plane_state {
@@ -64,6 +67,7 @@ struct exynos_drm_plane_state {
 	struct exynos_drm_rect src;
 	unsigned int h_ratio;
 	unsigned int v_ratio;
+	struct drm_framebuffer *fb;
 };
 
 static inline struct exynos_drm_plane_state *
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 2e2247126581..0046495173f3 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -650,7 +650,7 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
 	struct exynos_drm_plane_state *state =
 				to_exynos_plane_state(plane->base.state);
 	struct fimd_context *ctx = crtc->ctx;
-	struct drm_framebuffer *fb = state->base.fb;
+	struct drm_framebuffer *fb = state->fb;
 	dma_addr_t dma_addr;
 	unsigned long val, size, offset;
 	unsigned int last_x, last_y, buf_offsize, line_size;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 427aeec78a28..8a1242b5a938 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -117,6 +117,8 @@ static void exynos_plane_mode_set(struct exynos_drm_plane_state *exynos_state)
 	exynos_state->crtc.w = actual_w;
 	exynos_state->crtc.h = actual_h;
 
+	exynos_state->fb = state->fb;
+
 	DRM_DEBUG_KMS("plane : offset_x/y(%d,%d), width/height(%d,%d)",
 			exynos_state->crtc.x, exynos_state->crtc.y,
 			exynos_state->crtc.w, exynos_state->crtc.h);
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index dfb35e2da4db..787aa03f4359 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -425,7 +425,7 @@ static void vp_video_buffer(struct mixer_context *ctx,
 				to_exynos_plane_state(plane->base.state);
 	struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode;
 	struct mixer_resources *res = &ctx->mixer_res;
-	struct drm_framebuffer *fb = state->base.fb;
+	struct drm_framebuffer *fb = state->fb;
 	unsigned long flags;
 	dma_addr_t luma_addr[2], chroma_addr[2];
 	bool tiled_mode = false;
@@ -535,7 +535,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
 				to_exynos_plane_state(plane->base.state);
 	struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode;
 	struct mixer_resources *res = &ctx->mixer_res;
-	struct drm_framebuffer *fb = state->base.fb;
+	struct drm_framebuffer *fb = state->fb;
 	unsigned long flags;
 	unsigned int win = plane->zpos;
 	unsigned int x_ratio = 0, y_ratio = 0;
-- 
1.9.2

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

* [PATCH v2 17/22] drm/exynos: gem: set default alignment for dumb GEM buffers
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (15 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 16/22] drm/exynos: add fb pointer to exynos_drm_plane_state Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 18/22] drm/exynos: fix to calculate offset of each plane for ipp fimc Marek Szyprowski
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

This patch forces all GEM buffers to have pitch aligned at least to 8
pixels. This is a common requirement for various Exynos IPP blocks,
which otherwise won't be able to operate on buffers of random size.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 ++
 drivers/gpu/drm/exynos/exynos_drm_gem.c | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index bb2e449a20c3..670f6d06a2a9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -24,6 +24,8 @@
 
 #define DEFAULT_WIN	0
 
+#define EXYNOS_DRM_PITCH_ALIGN	8
+
 #define to_exynos_crtc(x)	container_of(x, struct exynos_drm_crtc, base)
 #define to_exynos_plane(x)	container_of(x, struct exynos_drm_plane, base)
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 252eb301470c..b5db6e6cc043 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -417,7 +417,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
 	 *	with DRM_IOCTL_MODE_CREATE_DUMB command.
 	 */
 
-	args->pitch = args->width * ((args->bpp + 7) / 8);
+	args->pitch = roundup(args->width, EXYNOS_DRM_PITCH_ALIGN) * ((args->bpp + 7) / 8);
 	args->size = args->pitch * args->height;
 
 	if (is_drm_iommu_supported(dev))
-- 
1.9.2

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

* [PATCH v2 18/22] drm/exynos: fix to calculate offset of each plane for ipp fimc
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (16 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 17/22] drm/exynos: gem: set default alignment for dumb GEM buffers Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 19/22] drm/exynos: fix to calculate offset of each plane for ipp gsc Marek Szyprowski
                   ` (4 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

From: Seung-Woo Kim <sw0312.kim@samsung.com>

NV12 and YUV420 formats are need to calculate offset of each plane
for ipp fimc in a gem buffer. Without proper offset, only Y plane
can be processed, so result shows green frame.
This patch fixes to calculate offset for cbcr planes for NV12 and
YUV420 formats.

Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_fimc.c | 106 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/exynos/exynos_drm_ipp.c  |  15 ++++-
 drivers/gpu/drm/exynos/exynos_drm_ipp.h  |   2 +
 3 files changed, 121 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index c747824f3c98..72a7ca188be5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -403,6 +403,97 @@ static void fimc_handle_lastend(struct fimc_context *ctx, bool enable)
 	fimc_write(ctx, cfg, EXYNOS_CIOCTRL);
 }
 
+static int fimc_set_planar_addr(struct drm_exynos_ipp_buf_info *buf_info,
+				u32 fmt, struct drm_exynos_sz *sz)
+{
+	dma_addr_t *base[EXYNOS_DRM_PLANAR_MAX];
+	uint64_t size[EXYNOS_DRM_PLANAR_MAX];
+	uint64_t ofs[EXYNOS_DRM_PLANAR_MAX];
+	bool bypass = false;
+	uint64_t tsize = 0;
+	int i;
+
+	for_each_ipp_planar(i) {
+		base[i] = &buf_info->base[i];
+		size[i] = buf_info->size[i];
+		ofs[i] = 0;
+		tsize += size[i];
+	}
+
+	if (!tsize) {
+		DRM_INFO("%s:failed to get buffer size.\n", __func__);
+		return 0;
+	}
+
+	switch (fmt) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+		ofs[0] = sz->hsize * sz->vsize;
+		ofs[1] = ofs[0] >> 1;
+		if (*base[0] && *base[1]) {
+			if (size[0] + size[1] < ofs[0] + ofs[1])
+				goto err_info;
+			bypass = true;
+		}
+		break;
+	case DRM_FORMAT_YUV410:
+	case DRM_FORMAT_YVU410:
+	case DRM_FORMAT_YUV411:
+	case DRM_FORMAT_YVU411:
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
+		ofs[0] = sz->hsize * sz->vsize;
+		ofs[1] = ofs[2] = ofs[0] >> 2;
+		if (*base[0] && *base[1] && *base[2]) {
+			if (size[0]+size[1]+size[2] < ofs[0]+ofs[1]+ofs[2])
+				goto err_info;
+			bypass = true;
+		}
+		break;
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+		ofs[0] = sz->hsize * sz->vsize << 2;
+		if (*base[0]) {
+			if (size[0] < ofs[0])
+				goto err_info;
+		}
+		bypass = true;
+		break;
+	default:
+		bypass = true;
+		break;
+	}
+
+	if (!bypass) {
+		*base[1] = *base[0] + ofs[0];
+		if (ofs[1] && ofs[2])
+			*base[2] = *base[1] + ofs[1];
+	}
+
+	DRM_DEBUG_KMS("%s:y[0x%x],cb[0x%x],cr[0x%x]\n", __func__,
+		*base[0], *base[1], *base[2]);
+
+	return 0;
+
+err_info:
+	DRM_ERROR("invalid size for fmt[0x%x]\n", fmt);
+
+	for_each_ipp_planar(i) {
+		base[i] = &buf_info->base[i];
+		size[i] = buf_info->size[i];
+
+		DRM_ERROR("buf[%d] - base[0x%x] sz[%llu] ofs[%llu]\n",
+			i, *base[i], size[i], ofs[i]);
+	}
+
+	return -EINVAL;
+}
 
 static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt)
 {
@@ -689,6 +780,7 @@ static int fimc_src_set_addr(struct device *dev,
 	struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
 	struct drm_exynos_ipp_property *property;
 	struct drm_exynos_ipp_config *config;
+	int ret;
 
 	if (!c_node) {
 		DRM_ERROR("failed to get c_node.\n");
@@ -709,6 +801,12 @@ static int fimc_src_set_addr(struct device *dev,
 	switch (buf_type) {
 	case IPP_BUF_ENQUEUE:
 		config = &property->config[EXYNOS_DRM_OPS_SRC];
+		ret = fimc_set_planar_addr(buf_info, config->fmt, &config->sz);
+		if (ret) {
+			dev_err(dev, "failed to set plane src addr.\n");
+			return ret;
+		}
+
 		fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_Y],
 			EXYNOS_CIIYSA0);
 
@@ -1148,6 +1246,7 @@ static int fimc_dst_set_addr(struct device *dev,
 	struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
 	struct drm_exynos_ipp_property *property;
 	struct drm_exynos_ipp_config *config;
+	int ret;
 
 	if (!c_node) {
 		DRM_ERROR("failed to get c_node.\n");
@@ -1168,6 +1267,11 @@ static int fimc_dst_set_addr(struct device *dev,
 	switch (buf_type) {
 	case IPP_BUF_ENQUEUE:
 		config = &property->config[EXYNOS_DRM_OPS_DST];
+		ret = fimc_set_planar_addr(buf_info, config->fmt, &config->sz);
+		if (ret) {
+			dev_err(dev, "failed to set plane dst addr.\n");
+			return ret;
+		}
 
 		fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_Y],
 			EXYNOS_CIOYSA(buf_id));
@@ -1562,6 +1666,8 @@ static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
 	/* reset sequence */
 	fimc_write(ctx, 0x0, EXYNOS_CIFCNTSEQ);
 
+	fimc_clear_addr(ctx);
+
 	/* Scaler disable */
 	fimc_clear_bits(ctx, EXYNOS_CISCCTRL, EXYNOS_CISCCTRL_SCALERSTART);
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index 67d24236e745..408a14a9a180 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -571,6 +571,7 @@ static struct drm_exynos_ipp_mem_node
 		/* get dma address by handle */
 		if (qbuf->handle[i]) {
 			dma_addr_t *addr;
+			unsigned long size;
 
 			addr = exynos_drm_gem_get_dma_addr(drm_dev,
 					qbuf->handle[i], c_node->filp);
@@ -580,10 +581,20 @@ static struct drm_exynos_ipp_mem_node
 				return ERR_PTR(-EFAULT);
 			}
 
+			size = exynos_drm_gem_get_size(drm_dev,
+					qbuf->handle[i], c_node->filp);
+			if (!size) {
+				DRM_ERROR("failed to get size.\n");
+				ipp_put_mem_node(drm_dev, c_node, m_node);
+				return ERR_PTR(-EFAULT);
+			}
+
 			buf_info->handles[i] = qbuf->handle[i];
 			buf_info->base[i] = *addr;
-			DRM_DEBUG_KMS("i[%d]base[0x%x]hd[0x%lx]\n", i,
-				      buf_info->base[i], buf_info->handles[i]);
+			buf_info->size[i] = (uint64_t)size;
+			DRM_DEBUG_KMS("i[%d]base[%pad]hd[0x%lx]sz[%llx]\n", i,
+				      &buf_info->base[i], buf_info->handles[i],
+				      buf_info->size[i]);
 		}
 	}
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.h b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
index 2a61547a39d0..d4f0b588220b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
@@ -85,10 +85,12 @@ struct drm_exynos_ipp_cmd_node {
  *
  * @handles: Y, Cb, Cr each gem object handle.
  * @base: Y, Cb, Cr each planar address.
+ * @size: Y, Cb, Cr each planar size.
  */
 struct drm_exynos_ipp_buf_info {
 	unsigned long	handles[EXYNOS_DRM_PLANAR_MAX];
 	dma_addr_t	base[EXYNOS_DRM_PLANAR_MAX];
+	uint64_t	size[EXYNOS_DRM_PLANAR_MAX];
 };
 
 /*
-- 
1.9.2

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

* [PATCH v2 19/22] drm/exynos: fix to calculate offset of each plane for ipp gsc
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (17 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 18/22] drm/exynos: fix to calculate offset of each plane for ipp fimc Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 20/22] drm/exynos: gem: simplify access to exynos gem object Marek Szyprowski
                   ` (3 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

From: Seung-Woo Kim <sw0312.kim@samsung.com>

NV12 and YUV420 formats are needed to calculate offset of each plane
in a gem buffer for ipp gsc. Without proper offset, only Y plane
can be processed, so result shows green frame. This patch fixes to
calculate offset for cbcr planes for NV12 and YUV420 formats.

Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_gsc.c | 116 ++++++++++++++++++++++++++++++++
 1 file changed, 116 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 7aecd23cfa11..2882b9347cc8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -486,6 +486,98 @@ static void gsc_handle_irq(struct gsc_context *ctx, bool enable,
 	gsc_write(cfg, GSC_IRQ);
 }
 
+static int gsc_set_planar_addr(struct drm_exynos_ipp_buf_info *buf_info,
+		u32 fmt, struct drm_exynos_sz *sz)
+{
+	dma_addr_t *base[EXYNOS_DRM_PLANAR_MAX];
+	uint64_t size[EXYNOS_DRM_PLANAR_MAX];
+	uint64_t ofs[EXYNOS_DRM_PLANAR_MAX];
+	bool bypass = false;
+	uint64_t tsize = 0;
+	int i;
+
+	for_each_ipp_planar(i) {
+		base[i] = &buf_info->base[i];
+		size[i] = buf_info->size[i];
+		ofs[i] = 0;
+		tsize += size[i];
+		DRM_DEBUG_KMS("base[%d][0x%lx]s[%d][%llu]\n",
+				i, (unsigned long)*base[i], i, size[i]);
+	}
+
+	if (!tsize) {
+		DRM_INFO("failed to get buffer size.\n");
+		return 0;
+	}
+
+	switch (fmt) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+		ofs[0] = sz->hsize * sz->vsize;
+		ofs[1] = ofs[0] >> 1;
+		if (*base[0] && *base[1]) {
+			if (size[0] + size[1] < ofs[0] + ofs[1])
+				goto err_info;
+			bypass = true;
+		}
+		break;
+	case DRM_FORMAT_YUV410:
+	case DRM_FORMAT_YVU410:
+	case DRM_FORMAT_YUV411:
+	case DRM_FORMAT_YVU411:
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
+		ofs[0] = sz->hsize * sz->vsize;
+		ofs[1] = ofs[2] = ofs[0] >> 2;
+		if (*base[0] && *base[1] && *base[2]) {
+			if (size[0]+size[1]+size[2] < ofs[0]+ofs[1]+ofs[2])
+				goto err_info;
+			bypass = true;
+		}
+	break;
+	case DRM_FORMAT_XRGB8888:
+		ofs[0] = sz->hsize * sz->vsize << 2;
+		if (*base[0]) {
+			if (size[0] < ofs[0])
+				goto err_info;
+		}
+		bypass = true;
+		break;
+	default:
+		bypass = true;
+		break;
+	}
+
+	if (!bypass) {
+		*base[1] = *base[0] + ofs[0];
+		if (ofs[1] && ofs[2])
+			*base[2] = *base[1] + ofs[1];
+	}
+
+	DRM_DEBUG_KMS("y[0x%lx],cb[0x%lx],cr[0x%lx]\n", (unsigned long)*base[0],
+			(unsigned long)*base[1], (unsigned long)*base[2]);
+
+	return 0;
+
+err_info:
+	DRM_ERROR("invalid size for fmt[0x%x]\n", fmt);
+
+	for_each_ipp_planar(i) {
+		base[i] = &buf_info->base[i];
+		size[i] = buf_info->size[i];
+
+		DRM_ERROR("base[%d][0x%lx]s[%d][%llu]ofs[%d][%llu]\n",
+			i, (unsigned long)*base[i], i, size[i], i, ofs[i]);
+	}
+
+	return -EINVAL;
+}
 
 static int gsc_src_set_fmt(struct device *dev, u32 fmt)
 {
@@ -715,6 +807,8 @@ static int gsc_src_set_addr(struct device *dev,
 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 	struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
 	struct drm_exynos_ipp_property *property;
+	struct drm_exynos_ipp_config *config;
+	int ret;
 
 	if (!c_node) {
 		DRM_ERROR("failed to get c_node.\n");
@@ -734,6 +828,13 @@ static int gsc_src_set_addr(struct device *dev,
 	/* address register set */
 	switch (buf_type) {
 	case IPP_BUF_ENQUEUE:
+		config = &property->config[EXYNOS_DRM_OPS_SRC];
+		ret = gsc_set_planar_addr(buf_info, config->fmt, &config->sz);
+		if (ret) {
+			dev_err(dev, "failed to set plane src addr.\n");
+			return ret;
+		}
+
 		gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
 			GSC_IN_BASE_ADDR_Y(buf_id));
 		gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
@@ -1170,6 +1271,8 @@ static int gsc_dst_set_addr(struct device *dev,
 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 	struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
 	struct drm_exynos_ipp_property *property;
+	struct drm_exynos_ipp_config *config;
+	int ret;
 
 	if (!c_node) {
 		DRM_ERROR("failed to get c_node.\n");
@@ -1189,6 +1292,13 @@ static int gsc_dst_set_addr(struct device *dev,
 	/* address register set */
 	switch (buf_type) {
 	case IPP_BUF_ENQUEUE:
+		config = &property->config[EXYNOS_DRM_OPS_DST];
+		ret = gsc_set_planar_addr(buf_info, config->fmt, &config->sz);
+		if (ret) {
+			dev_err(dev, "failed to set plane dst addr.\n");
+			return ret;
+		}
+
 		gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
 			GSC_OUT_BASE_ADDR_Y(buf_id));
 		gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
@@ -1320,6 +1430,12 @@ static irqreturn_t gsc_irq_handler(int irq, void *dev_id)
 		return IRQ_NONE;
 	}
 
+	if (c_node->state == IPP_STATE_STOP) {
+		DRM_ERROR("invalid state: prop_id[%d]\n",
+				c_node->property.prop_id);
+		return IRQ_HANDLED;
+	}
+
 	if (status & GSC_IRQ_STATUS_OR_FRM_DONE) {
 		dev_dbg(ippdrv->dev, "occurred frame done at %d, status 0x%x.\n",
 			ctx->id, status);
-- 
1.9.2

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

* [PATCH v2 20/22] drm/exynos: gem: simplify access to exynos gem object
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (18 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 19/22] drm/exynos: fix to calculate offset of each plane for ipp gsc Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 21/22] drm/exynos: ipp: make framework context global Marek Szyprowski
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Andrzej Hajda, Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz,
	Tobias Jakobi, Gustavo Padovan, Javier Martinez Canillas

Replace calls to exynos_drm_gem_get_{dma_addr,size}, by a simpler
function exynos_drm_gem_get(). This lets the caller to get access to
exynos_drm_gem object and extract any information about GEM object
without searching object tree for getting each parameter.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_g2d.c | 48 +++++++++++++-----------------
 drivers/gpu/drm/exynos/exynos_drm_gem.c | 52 +++++----------------------------
 drivers/gpu/drm/exynos/exynos_drm_gem.h | 23 +++++----------
 drivers/gpu/drm/exynos/exynos_drm_ipp.c | 41 ++++++++++----------------
 drivers/gpu/drm/exynos/exynos_drm_ipp.h |  2 +-
 5 files changed, 52 insertions(+), 114 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index c17efdb238a6..7c83e64f9f1c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -179,7 +179,7 @@ struct g2d_buf_desc {
 struct g2d_buf_info {
 	unsigned int		map_nr;
 	enum g2d_reg_type	reg_types[MAX_REG_TYPE_NR];
-	unsigned long		handles[MAX_REG_TYPE_NR];
+	void			*obj[MAX_REG_TYPE_NR];
 	unsigned int		types[MAX_REG_TYPE_NR];
 	struct g2d_buf_desc	descs[MAX_REG_TYPE_NR];
 };
@@ -360,11 +360,10 @@ add_to_list:
 }
 
 static void g2d_userptr_put_dma_addr(struct drm_device *drm_dev,
-					unsigned long obj,
+					void *obj,
 					bool force)
 {
-	struct g2d_cmdlist_userptr *g2d_userptr =
-					(struct g2d_cmdlist_userptr *)obj;
+	struct g2d_cmdlist_userptr *g2d_userptr = obj;
 	struct page **pages;
 
 	if (!obj)
@@ -407,7 +406,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
 					unsigned long userptr,
 					unsigned long size,
 					struct drm_file *filp,
-					unsigned long *obj)
+					void **obj)
 {
 	struct drm_exynos_file_private *file_priv = filp->driver_priv;
 	struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
@@ -434,7 +433,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
 			 */
 			if (g2d_userptr->size == size) {
 				atomic_inc(&g2d_userptr->refcount);
-				*obj = (unsigned long)g2d_userptr;
+				*obj = g2d_userptr;
 
 				return &g2d_userptr->dma_addr;
 			}
@@ -517,7 +516,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
 		g2d_userptr->in_pool = true;
 	}
 
-	*obj = (unsigned long)g2d_userptr;
+	*obj = g2d_userptr;
 
 	return &g2d_userptr->dma_addr;
 
@@ -549,9 +548,7 @@ static void g2d_userptr_free_all(struct drm_device *drm_dev,
 
 	list_for_each_entry_safe(g2d_userptr, n, &g2d_priv->userptr_list, list)
 		if (g2d_userptr->in_pool)
-			g2d_userptr_put_dma_addr(drm_dev,
-						(unsigned long)g2d_userptr,
-						true);
+			g2d_userptr_put_dma_addr(drm_dev, g2d_userptr, true);
 
 	g2d->current_pool = 0;
 }
@@ -706,26 +703,23 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
 		buf_desc = &buf_info->descs[reg_type];
 
 		if (buf_info->types[reg_type] == BUF_TYPE_GEM) {
-			unsigned long size;
+			struct exynos_drm_gem *exynos_gem;
 
-			size = exynos_drm_gem_get_size(drm_dev, handle, file);
-			if (!size) {
+			exynos_gem = exynos_drm_gem_get(drm_dev, handle, file);
+			if (IS_ERR(exynos_gem)) {
 				ret = -EFAULT;
 				goto err;
 			}
 
 			if (!g2d_check_buf_desc_is_valid(buf_desc, reg_type,
-									size)) {
+							 exynos_gem->size)) {
+				exynos_drm_gem_put(drm_dev, exynos_gem);
 				ret = -EFAULT;
 				goto err;
 			}
 
-			addr = exynos_drm_gem_get_dma_addr(drm_dev, handle,
-								file);
-			if (IS_ERR(addr)) {
-				ret = -EFAULT;
-				goto err;
-			}
+			addr = &exynos_gem->dma_addr;
+			buf_info->obj[reg_type] = exynos_gem;
 		} else {
 			struct drm_exynos_g2d_userptr g2d_userptr;
 
@@ -745,7 +739,7 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
 							g2d_userptr.userptr,
 							g2d_userptr.size,
 							file,
-							&handle);
+							&buf_info->obj[reg_type]);
 			if (IS_ERR(addr)) {
 				ret = -EFAULT;
 				goto err;
@@ -754,7 +748,6 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
 
 		cmdlist->data[reg_pos + 1] = *addr;
 		buf_info->reg_types[i] = reg_type;
-		buf_info->handles[reg_type] = handle;
 	}
 
 	return 0;
@@ -775,22 +768,21 @@ static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d,
 	for (i = 0; i < buf_info->map_nr; i++) {
 		struct g2d_buf_desc *buf_desc;
 		enum g2d_reg_type reg_type;
-		unsigned long handle;
+		void *obj;
 
 		reg_type = buf_info->reg_types[i];
 
 		buf_desc = &buf_info->descs[reg_type];
-		handle = buf_info->handles[reg_type];
+		obj = buf_info->obj[reg_type];
 
 		if (buf_info->types[reg_type] == BUF_TYPE_GEM)
-			exynos_drm_gem_put_dma_addr(subdrv->drm_dev, handle,
-							filp);
+			exynos_drm_gem_put(subdrv->drm_dev, obj);
 		else
-			g2d_userptr_put_dma_addr(subdrv->drm_dev, handle,
+			g2d_userptr_put_dma_addr(subdrv->drm_dev, obj,
 							false);
 
 		buf_info->reg_types[i] = REG_TYPE_NONE;
-		buf_info->handles[reg_type] = 0;
+		buf_info->obj[reg_type] = NULL;
 		buf_info->types[reg_type] = 0;
 		memset(buf_desc, 0x00, sizeof(*buf_desc));
 	}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index b5db6e6cc043..382e65df5c03 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -169,26 +169,6 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem *exynos_gem)
 	kfree(exynos_gem);
 }
 
-unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
-						unsigned int gem_handle,
-						struct drm_file *file_priv)
-{
-	struct exynos_drm_gem *exynos_gem;
-	struct drm_gem_object *obj;
-
-	obj = drm_gem_object_lookup(dev, file_priv, gem_handle);
-	if (!obj) {
-		DRM_ERROR("failed to lookup gem object.\n");
-		return 0;
-	}
-
-	exynos_gem = to_exynos_gem(obj);
-
-	drm_gem_object_unreference_unlocked(obj);
-
-	return exynos_gem->size;
-}
-
 static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev,
 						  unsigned long size)
 {
@@ -279,11 +259,10 @@ int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
 	return 0;
 }
 
-dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
-					unsigned int gem_handle,
-					struct drm_file *filp)
+struct exynos_drm_gem *exynos_drm_gem_get(struct drm_device *dev,
+					  unsigned int gem_handle,
+					  struct drm_file *filp)
 {
-	struct exynos_drm_gem *exynos_gem;
 	struct drm_gem_object *obj;
 
 	obj = drm_gem_object_lookup(dev, filp, gem_handle);
@@ -292,30 +271,13 @@ dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
 		return ERR_PTR(-EINVAL);
 	}
 
-	exynos_gem = to_exynos_gem(obj);
-
-	return &exynos_gem->dma_addr;
+	return to_exynos_gem(obj);
 }
 
-void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
-					unsigned int gem_handle,
-					struct drm_file *filp)
+void exynos_drm_gem_put(struct drm_device *dev,
+			struct exynos_drm_gem *exynos_gem)
 {
-	struct drm_gem_object *obj;
-
-	obj = drm_gem_object_lookup(dev, filp, gem_handle);
-	if (!obj) {
-		DRM_ERROR("failed to lookup gem object.\n");
-		return;
-	}
-
-	drm_gem_object_unreference_unlocked(obj);
-
-	/*
-	 * decrease obj->refcount one more time because we has already
-	 * increased it at exynos_drm_gem_get_dma_addr().
-	 */
-	drm_gem_object_unreference_unlocked(obj);
+	drm_gem_object_unreference_unlocked(&exynos_gem->base);
 }
 
 static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
index 9ca5047959ec..d4a49985c8ab 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -72,32 +72,25 @@ int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
 
 /*
- * get dma address from gem handle and this function could be used for
+ * get exynos drm object from gem handle, this function could be used for
  * other drivers such as 2d/3d acceleration drivers.
  * with this function call, gem object reference count would be increased.
  */
-dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
-					unsigned int gem_handle,
-					struct drm_file *filp);
+struct exynos_drm_gem *exynos_drm_gem_get(struct drm_device *dev,
+					  unsigned int gem_handle,
+					  struct drm_file *filp);
 
 /*
- * put dma address from gem handle and this function could be used for
- * other drivers such as 2d/3d acceleration drivers.
- * with this function call, gem object reference count would be decreased.
+ * put exynos drm object acquired from exynos_drm_gem_get(),
+ * gem object reference count would be decreased.
  */
-void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
-					unsigned int gem_handle,
-					struct drm_file *filp);
+void exynos_drm_gem_put(struct drm_device *dev,
+			struct exynos_drm_gem *exynos_gem);
 
 /* get buffer information to memory region allocated by gem. */
 int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
 				      struct drm_file *file_priv);
 
-/* get buffer size to gem handle. */
-unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
-						unsigned int gem_handle,
-						struct drm_file *file_priv);
-
 /* free gem object. */
 void exynos_drm_gem_free_object(struct drm_gem_object *obj);
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index 408a14a9a180..0404e18d84cc 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -488,10 +488,9 @@ static int ipp_validate_mem_node(struct drm_device *drm_dev,
 		plane_size = width * height * bpp;
 		img_size += plane_size;
 
-		if (m_node->buf_info.handles[i]) {
-			size = exynos_drm_gem_get_size(drm_dev,
-					m_node->buf_info.handles[i],
-					c_node->filp);
+		if (m_node->buf_info.obj[i]) {
+			size = m_node->buf_info.obj[i]->size;
+
 			if (plane_size > size) {
 				DRM_ERROR(
 					"buffer %d is smaller than required\n",
@@ -529,10 +528,9 @@ static int ipp_put_mem_node(struct drm_device *drm_dev,
 
 	/* put gem buffer */
 	for_each_ipp_planar(i) {
-		unsigned long handle = m_node->buf_info.handles[i];
-		if (handle)
-			exynos_drm_gem_put_dma_addr(drm_dev, handle,
-							c_node->filp);
+		struct exynos_drm_gem *obj = m_node->buf_info.obj[i];
+		if (obj)
+			exynos_drm_gem_put(drm_dev, obj);
 	}
 
 	list_del(&m_node->list);
@@ -570,30 +568,23 @@ static struct drm_exynos_ipp_mem_node
 
 		/* get dma address by handle */
 		if (qbuf->handle[i]) {
-			dma_addr_t *addr;
-			unsigned long size;
+			struct exynos_drm_gem *exynos_gem;
 
-			addr = exynos_drm_gem_get_dma_addr(drm_dev,
-					qbuf->handle[i], c_node->filp);
-			if (IS_ERR(addr)) {
-				DRM_ERROR("failed to get addr.\n");
-				ipp_put_mem_node(drm_dev, c_node, m_node);
-				return ERR_PTR(-EFAULT);
-			}
+			exynos_gem = exynos_drm_gem_get(drm_dev,
+						qbuf->handle[i], c_node->filp);
 
-			size = exynos_drm_gem_get_size(drm_dev,
-					qbuf->handle[i], c_node->filp);
-			if (!size) {
-				DRM_ERROR("failed to get size.\n");
+			if (IS_ERR(exynos_gem)) {
+				DRM_ERROR("failed to get gem.\n");
 				ipp_put_mem_node(drm_dev, c_node, m_node);
 				return ERR_PTR(-EFAULT);
 			}
 
-			buf_info->handles[i] = qbuf->handle[i];
-			buf_info->base[i] = *addr;
-			buf_info->size[i] = (uint64_t)size;
+			buf_info->obj[i] = exynos_gem;
+			buf_info->base[i] = exynos_gem->dma_addr;
+			buf_info->size[i] = exynos_gem->size;
 			DRM_DEBUG_KMS("i[%d]base[%pad]hd[0x%lx]sz[%llx]\n", i,
-				      &buf_info->base[i], buf_info->handles[i],
+				      &buf_info->base[i],
+				      (long unsigned)qbuf->handle[i],
 				      buf_info->size[i]);
 		}
 	}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.h b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
index d4f0b588220b..1dc13bf57b16 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
@@ -88,7 +88,7 @@ struct drm_exynos_ipp_cmd_node {
  * @size: Y, Cb, Cr each planar size.
  */
 struct drm_exynos_ipp_buf_info {
-	unsigned long	handles[EXYNOS_DRM_PLANAR_MAX];
+	struct exynos_drm_gem	*obj[EXYNOS_DRM_PLANAR_MAX];
 	dma_addr_t	base[EXYNOS_DRM_PLANAR_MAX];
 	uint64_t	size[EXYNOS_DRM_PLANAR_MAX];
 };
-- 
1.9.2

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

* [PATCH v2 21/22] drm/exynos: ipp: make framework context global
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (19 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 20/22] drm/exynos: gem: simplify access to exynos gem object Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2015-11-30 13:53 ` [PATCH v2 22/22] drm/exynos: add support for plane rotation, scalling and colospace convesion Marek Szyprowski
  2016-03-15 14:46 ` [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Tobias Jakobi
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Javier Martinez Canillas, Krzysztof Kozlowski,
	Bartlomiej Zolnierkiewicz, Seung-Woo Kim, Andrzej Hajda,
	Tobias Jakobi, Marek Szyprowski

IPP framework stored global context in driver data of its platform device.
This patch moves it to global variable to simplify access. There exists
only one such framework, so there is no drawback of this change.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_ipp.c | 50 ++++++++++-----------------------
 1 file changed, 15 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index 0404e18d84cc..44a6689e0f4c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -42,7 +42,6 @@
  * 7. need to power_on implement power and sysmmu ctrl.
  */
 
-#define get_ipp_context(dev)	platform_get_drvdata(to_platform_device(dev))
 #define ipp_is_m2m_cmd(c)	(c == IPP_CMD_M2M)
 
 /*
@@ -95,6 +94,7 @@ struct ipp_context {
 	struct workqueue_struct	*cmd_workq;
 };
 
+static struct ipp_context *ctx;
 static LIST_HEAD(exynos_drm_ippdrv_list);
 static DEFINE_MUTEX(exynos_drm_ippdrv_lock);
 static BLOCKING_NOTIFIER_HEAD(exynos_drm_ippnb_list);
@@ -226,9 +226,6 @@ static struct exynos_drm_ippdrv *ipp_find_drv_by_handle(u32 prop_id)
 int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
 		struct drm_file *file)
 {
-	struct drm_exynos_file_private *file_priv = file->driver_priv;
-	struct device *dev = file_priv->ipp_dev;
-	struct ipp_context *ctx = get_ipp_context(dev);
 	struct drm_exynos_ipp_prop_list *prop_list = data;
 	struct exynos_drm_ippdrv *ippdrv;
 	int count = 0;
@@ -320,9 +317,6 @@ static struct drm_exynos_ipp_event_work *ipp_create_event_work(void)
 int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
 		struct drm_file *file)
 {
-	struct drm_exynos_file_private *file_priv = file->driver_priv;
-	struct device *dev = file_priv->ipp_dev;
-	struct ipp_context *ctx = get_ipp_context(dev);
 	struct drm_exynos_ipp_property *property = data;
 	struct exynos_drm_ippdrv *ippdrv;
 	struct drm_exynos_ipp_cmd_node *c_node;
@@ -803,22 +797,18 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv,
 	return ret;
 }
 
-static void ipp_handle_cmd_work(struct device *dev,
-		struct exynos_drm_ippdrv *ippdrv,
-		struct drm_exynos_ipp_cmd_work *cmd_work,
-		struct drm_exynos_ipp_cmd_node *c_node)
+static void ipp_handle_cmd_work(struct exynos_drm_ippdrv *ippdrv,
+				struct drm_exynos_ipp_cmd_work *cmd_work,
+				struct drm_exynos_ipp_cmd_node *c_node)
 {
-	struct ipp_context *ctx = get_ipp_context(dev);
-
 	cmd_work->ippdrv = ippdrv;
 	cmd_work->c_node = c_node;
 	queue_work(ctx->cmd_workq, &cmd_work->work);
 }
 
-static int ipp_queue_buf_with_run(struct device *dev,
-		struct drm_exynos_ipp_cmd_node *c_node,
-		struct drm_exynos_ipp_mem_node *m_node,
-		struct drm_exynos_ipp_queue_buf *qbuf)
+static int ipp_queue_buf_with_run(struct drm_exynos_ipp_cmd_node *c_node,
+				  struct drm_exynos_ipp_mem_node *m_node,
+				  struct drm_exynos_ipp_queue_buf *qbuf)
 {
 	struct exynos_drm_ippdrv *ippdrv;
 	struct drm_exynos_ipp_property *property;
@@ -859,7 +849,7 @@ static int ipp_queue_buf_with_run(struct device *dev,
 		struct drm_exynos_ipp_cmd_work *cmd_work = c_node->start_work;
 
 		cmd_work->ctrl = IPP_CTRL_PLAY;
-		ipp_handle_cmd_work(dev, ippdrv, cmd_work, c_node);
+		ipp_handle_cmd_work(ippdrv, cmd_work, c_node);
 	} else {
 		ret = ipp_set_mem_node(ippdrv, c_node, m_node);
 		if (ret) {
@@ -893,9 +883,6 @@ static void ipp_clean_queue_buf(struct drm_device *drm_dev,
 int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
 		struct drm_file *file)
 {
-	struct drm_exynos_file_private *file_priv = file->driver_priv;
-	struct device *dev = file_priv->ipp_dev;
-	struct ipp_context *ctx = get_ipp_context(dev);
 	struct drm_exynos_ipp_queue_buf *qbuf = data;
 	struct drm_exynos_ipp_cmd_node *c_node;
 	struct drm_exynos_ipp_mem_node *m_node;
@@ -950,7 +937,7 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
 			 * M2M case run play control for streaming feature.
 			 * other case set address and waiting.
 			 */
-			ret = ipp_queue_buf_with_run(dev, c_node, m_node, qbuf);
+			ret = ipp_queue_buf_with_run(c_node, m_node, qbuf);
 			if (ret) {
 				DRM_ERROR("failed to run command.\n");
 				goto err_clean_node;
@@ -1024,10 +1011,7 @@ err_status:
 int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
 		struct drm_file *file)
 {
-	struct drm_exynos_file_private *file_priv = file->driver_priv;
 	struct exynos_drm_ippdrv *ippdrv = NULL;
-	struct device *dev = file_priv->ipp_dev;
-	struct ipp_context *ctx = get_ipp_context(dev);
 	struct drm_exynos_ipp_cmd_ctrl *cmd_ctrl = data;
 	struct drm_exynos_ipp_cmd_work *cmd_work;
 	struct drm_exynos_ipp_cmd_node *c_node;
@@ -1073,12 +1057,12 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
 
 		cmd_work = c_node->start_work;
 		cmd_work->ctrl = cmd_ctrl->ctrl;
-		ipp_handle_cmd_work(dev, ippdrv, cmd_work, c_node);
+		ipp_handle_cmd_work(ippdrv, cmd_work, c_node);
 		break;
 	case IPP_CTRL_STOP:
 		cmd_work = c_node->stop_work;
 		cmd_work->ctrl = cmd_ctrl->ctrl;
-		ipp_handle_cmd_work(dev, ippdrv, cmd_work, c_node);
+		ipp_handle_cmd_work(ippdrv, cmd_work, c_node);
 
 		if (!wait_for_completion_timeout(&c_node->stop_complete,
 		    msecs_to_jiffies(300))) {
@@ -1098,7 +1082,7 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
 	case IPP_CTRL_PAUSE:
 		cmd_work = c_node->stop_work;
 		cmd_work->ctrl = cmd_ctrl->ctrl;
-		ipp_handle_cmd_work(dev, ippdrv, cmd_work, c_node);
+		ipp_handle_cmd_work(ippdrv, cmd_work, c_node);
 
 		if (!wait_for_completion_timeout(&c_node->stop_complete,
 		    msecs_to_jiffies(200))) {
@@ -1112,7 +1096,7 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
 		c_node->state = IPP_STATE_START;
 		cmd_work = c_node->start_work;
 		cmd_work->ctrl = cmd_ctrl->ctrl;
-		ipp_handle_cmd_work(dev, ippdrv, cmd_work, c_node);
+		ipp_handle_cmd_work(ippdrv, cmd_work, c_node);
 		break;
 	default:
 		DRM_ERROR("could not support this state currently.\n");
@@ -1597,7 +1581,6 @@ err_completion:
 
 static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
 {
-	struct ipp_context *ctx = get_ipp_context(dev);
 	struct exynos_drm_ippdrv *ippdrv;
 	int ret, count = 0;
 
@@ -1649,7 +1632,6 @@ err:
 static void ipp_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
 {
 	struct exynos_drm_ippdrv *ippdrv, *t;
-	struct ipp_context *ctx = get_ipp_context(dev);
 
 	/* get ipp driver entry */
 	list_for_each_entry_safe(ippdrv, t, &exynos_drm_ippdrv_list, drv_list) {
@@ -1679,7 +1661,6 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
 		struct drm_file *file)
 {
 	struct exynos_drm_ippdrv *ippdrv = NULL;
-	struct ipp_context *ctx = get_ipp_context(dev);
 	struct drm_exynos_ipp_cmd_node *c_node, *tc_node;
 	int count = 0;
 
@@ -1718,7 +1699,6 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
 static int ipp_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct ipp_context *ctx;
 	struct exynos_drm_subdrv *subdrv;
 	int ret;
 
@@ -1787,8 +1767,6 @@ err_event_workq:
 
 static int ipp_remove(struct platform_device *pdev)
 {
-	struct ipp_context *ctx = platform_get_drvdata(pdev);
-
 	/* unregister sub driver */
 	exynos_drm_subdrv_unregister(&ctx->subdrv);
 
@@ -1803,6 +1781,8 @@ static int ipp_remove(struct platform_device *pdev)
 	destroy_workqueue(ctx->cmd_workq);
 	destroy_workqueue(ctx->event_workq);
 
+	ctx = NULL;
+
 	return 0;
 }
 
-- 
1.9.2

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

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

* [PATCH v2 22/22] drm/exynos: add support for plane rotation, scalling and colospace convesion
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (20 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 21/22] drm/exynos: ipp: make framework context global Marek Szyprowski
@ 2015-11-30 13:53 ` Marek Szyprowski
  2016-03-15 14:46 ` [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Tobias Jakobi
  22 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-11-30 13:53 UTC (permalink / raw)
  To: dri-devel, linux-samsung-soc
  Cc: Javier Martinez Canillas, Krzysztof Kozlowski,
	Bartlomiej Zolnierkiewicz, Seung-Woo Kim, Andrzej Hajda,
	Tobias Jakobi, Marek Szyprowski

This patch adds generic plane rotation property for all supported
drivers. This has been implemented with additional help from Exynos IPP
(Exynos Image Post-Processing subsystem) with temporary framebuffers.
Besides rotation, scaling and color space conversion are also supported.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/Kconfig                |   8 +
 drivers/gpu/drm/exynos/Makefile               |   1 +
 drivers/gpu/drm/exynos/exynos_drm_drv.h       |   9 +
 drivers/gpu/drm/exynos/exynos_drm_ipp.c       | 154 ++++++++++-
 drivers/gpu/drm/exynos/exynos_drm_ipp.h       |   4 +
 drivers/gpu/drm/exynos/exynos_drm_plane.c     |  28 +-
 drivers/gpu/drm/exynos/exynos_drm_plane_ipp.c | 369 ++++++++++++++++++++++++++
 drivers/gpu/drm/exynos/exynos_drm_plane_ipp.h |  73 +++++
 8 files changed, 641 insertions(+), 5 deletions(-)
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_plane_ipp.c
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_plane_ipp.h

diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 83efca941388..e7d414aefbdc 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -104,6 +104,14 @@ config DRM_EXYNOS_IPP
 	help
 	  Choose this option if you want to use IPP feature for DRM.
 
+config DRM_EXYNOS_PLANE_IPP
+	depends on DRM_EXYNOS_IPP
+	bool "Use IPP framework for implementing unsupported plane properties"
+	help
+	  Choose this option if you want to let IPP framework to provide plane
+	  properties (like rotation, overlay scaling and more pixel formats),
+	  which are not supported by hardware CRTC drivers.
+
 config DRM_EXYNOS_FIMC
 	bool "FIMC"
 	depends on DRM_EXYNOS_IPP && MFD_SYSCON
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index 6496532aaa91..92c3f7cac7a9 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -19,6 +19,7 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)	+= exynos_hdmi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI)	+= exynos_drm_vidi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_G2D)	+= exynos_drm_g2d.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_IPP)	+= exynos_drm_ipp.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_PLANE_IPP)	+= exynos_drm_plane_ipp.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_FIMC)	+= exynos_drm_fimc.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_ROTATOR)	+= exynos_drm_rotator.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_GSC)	+= exynos_drm_gsc.o
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 670f6d06a2a9..b17e419935db 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -70,6 +70,13 @@ struct exynos_drm_plane_state {
 	unsigned int h_ratio;
 	unsigned int v_ratio;
 	struct drm_framebuffer *fb;
+	unsigned int rotation;
+
+	unsigned int ipp_needed;
+	uint32_t ipp_pixel_format;
+	struct exynos_drm_rect ipp_src;
+	struct exynos_drm_rect ipp_dst;
+	struct drm_framebuffer *ipp_fb;
 };
 
 static inline struct exynos_drm_plane_state *
@@ -93,6 +100,8 @@ struct exynos_drm_plane {
 	const struct exynos_drm_plane_config *config;
 	unsigned int zpos;
 	struct drm_framebuffer *pending_fb;
+	struct drm_framebuffer *ipp_cur_fb;
+	struct drm_framebuffer *ipp_next_fb;
 };
 
 #define EXYNOS_DRM_PLANE_CAP_DOUBLE	(1 << 0)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index 44a6689e0f4c..231cfbfe036c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -20,6 +20,7 @@
 #include <drm/drmP.h>
 #include <drm/exynos_drm.h>
 #include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
 #include "exynos_drm_gem.h"
 #include "exynos_drm_ipp.h"
 #include "exynos_drm_iommu.h"
@@ -1513,7 +1514,7 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
 
 	spin_lock_irqsave(&drm_dev->event_lock, flags);
 	list_move_tail(&e->base.link, &e->base.file_priv->event_list);
-	wake_up_interruptible(&e->base.file_priv->event_wait);
+	wake_up(&e->base.file_priv->event_wait);
 	spin_unlock_irqrestore(&drm_dev->event_lock, flags);
 	mutex_unlock(&c_node->event_lock);
 
@@ -1579,6 +1580,157 @@ err_completion:
 		complete(&c_node->start_complete);
 }
 
+static struct drm_exynos_ipp_mem_node
+		*ipp_get_internal_mem_node(struct drm_device *drm_dev,
+		struct drm_exynos_ipp_cmd_node *c_node,
+		__u32 prop_id, enum drm_exynos_ops_id ops_id,
+		struct drm_framebuffer *fb)
+{
+	struct drm_exynos_ipp_mem_node *m_node;
+	struct drm_exynos_ipp_buf_info *buf_info;
+	int i;
+
+	m_node = kzalloc(sizeof(*m_node), GFP_KERNEL);
+	if (!m_node)
+		return ERR_PTR(-ENOMEM);
+
+	buf_info = &m_node->buf_info;
+
+	m_node->ops_id = ops_id;
+	m_node->prop_id = prop_id;
+	INIT_LIST_HEAD(&m_node->list);
+
+	DRM_DEBUG_KMS("m_node[0x%x]ops_id[%d]prop_id[%d]\n", (int)m_node, ops_id, prop_id);
+
+	for_each_ipp_planar(i) {
+		buf_info->obj[i] = NULL;
+		buf_info->base[i] = exynos_drm_fb_dma_addr(fb, i);
+		buf_info->size[i] = fb->pitches[i] * fb->height;
+	}
+
+	mutex_lock(&c_node->mem_lock);
+	list_add_tail(&m_node->list, &c_node->mem_list[ops_id]);
+	mutex_unlock(&c_node->mem_lock);
+
+	return m_node;
+}
+
+
+static int exynos_drm_ipp_internal_enqueue_buf(struct drm_device *drm_dev,
+		__u32 prop_id, enum drm_exynos_ops_id ops_id,
+		struct drm_framebuffer *fb)
+{
+	struct drm_exynos_ipp_cmd_node *c_node;
+	struct drm_exynos_ipp_mem_node *m_node;
+	int ret;
+	struct drm_exynos_ipp_queue_buf qbuf = {
+		.ops_id = ops_id,
+		.buf_type = IPP_BUF_ENQUEUE,
+		.prop_id = prop_id,
+	};
+
+	DRM_DEBUG_KMS("prop_id[%d]ops_id[%s]\n",
+		prop_id, ops_id ? "dst" : "src");
+
+	c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock, prop_id);
+	if (!c_node) {
+		DRM_ERROR("failed to get command node.\n");
+		return -ENODEV;
+	}
+
+	m_node = ipp_get_internal_mem_node(drm_dev, c_node, prop_id,
+					   ops_id, fb);
+	if (IS_ERR(m_node)) {
+		DRM_ERROR("failed to get m_node.\n");
+		return PTR_ERR(m_node);
+	}
+
+	if (ops_id == EXYNOS_DRM_OPS_DST) {
+		ret = ipp_get_event(drm_dev, c_node, &qbuf);
+		if (ret) {
+			DRM_ERROR("failed to get event.\n");
+			goto err_clean_node;
+		}
+
+		ret = ipp_queue_buf_with_run(c_node, m_node, &qbuf);
+		if (ret) {
+			DRM_ERROR("failed to run command.\n");
+			goto err_clean_node;
+		}
+	}
+
+	return 0;
+
+err_clean_node:
+	DRM_ERROR("clean memory nodes.\n");
+
+	ipp_clean_queue_buf(drm_dev, c_node, &qbuf);
+	return ret;
+}
+
+int exynos_ipp_process_internal(struct drm_device *drm_dev,
+	struct drm_exynos_ipp_config *src_conf, struct drm_framebuffer *src_fb,
+	struct drm_exynos_ipp_config *dst_conf, struct drm_framebuffer *dst_fb)
+{
+	int ret;
+	struct drm_exynos_ipp_property property = {
+		.config = {
+			*src_conf,
+			*dst_conf,
+		},
+		.cmd = IPP_CMD_M2M,
+	};
+	struct drm_exynos_ipp_cmd_ctrl ctrl = {
+		/* .prop_id */
+		.ctrl = IPP_CTRL_PLAY,
+	};
+	struct drm_exynos_ipp_cmd_ctrl ctrl_stop = {
+		/* .prop_id */
+		.ctrl = IPP_CTRL_STOP,
+	};
+	struct drm_file virt_file = { };
+
+	INIT_LIST_HEAD(&virt_file.lhead);
+	INIT_LIST_HEAD(&virt_file.fbs);
+	mutex_init(&virt_file.fbs_lock);
+	INIT_LIST_HEAD(&virt_file.blobs);
+	INIT_LIST_HEAD(&virt_file.event_list);
+	init_waitqueue_head(&virt_file.event_wait);
+	virt_file.event_space = 4096;
+	virt_file.uid = current_euid();
+	virt_file.pid = get_pid(task_pid(current));
+	virt_file.authenticated = capable(CAP_SYS_ADMIN);
+	virt_file.lock_count = 0;
+
+	ret = exynos_drm_ipp_set_property(drm_dev, &property, &virt_file);
+	if (ret)
+		return ret;
+
+	ctrl.prop_id = property.prop_id;
+	ctrl_stop.prop_id = property.prop_id;
+
+	ret = exynos_drm_ipp_internal_enqueue_buf(drm_dev, property.prop_id,
+						  EXYNOS_DRM_OPS_SRC, src_fb);
+	if (ret)
+		goto cleanup;
+
+	ret = exynos_drm_ipp_internal_enqueue_buf(drm_dev, property.prop_id,
+						  EXYNOS_DRM_OPS_DST, dst_fb);
+	if (ret)
+		goto cleanup;
+
+	ret = exynos_drm_ipp_cmd_ctrl(drm_dev, &ctrl, &virt_file);
+	if (ret)
+		goto cleanup;
+
+	wait_event(virt_file.event_wait, !list_empty(&virt_file.event_list));
+
+cleanup:
+	exynos_drm_ipp_cmd_ctrl(drm_dev, &ctrl_stop, &virt_file);
+
+	return ret;
+}
+
 static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
 {
 	struct exynos_drm_ippdrv *ippdrv;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.h b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
index 1dc13bf57b16..7e95437edecb 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
@@ -24,6 +24,10 @@
 #define IPP_GET_LCD_HEIGHT	_IOR('F', 303, int)
 #define IPP_SET_WRITEBACK	_IOW('F', 304, u32)
 
+int exynos_ipp_process_internal(struct drm_device *drm_dev,
+	struct drm_exynos_ipp_config *src_conf, struct drm_framebuffer *src_fb,
+	struct drm_exynos_ipp_config *dst_conf, struct drm_framebuffer *dst_fb);
+
 /* definition of state */
 enum drm_exynos_ipp_state {
 	IPP_STATE_IDLE,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 8a1242b5a938..34ed1d6b8184 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -19,6 +19,7 @@
 #include "exynos_drm_fb.h"
 #include "exynos_drm_gem.h"
 #include "exynos_drm_plane.h"
+#include "exynos_drm_plane_ipp.h"
 
 /*
  * This function is to get X or Y size shown via screen. This needs length and
@@ -56,7 +57,8 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last)
 	return size;
 }
 
-static void exynos_plane_mode_set(struct exynos_drm_plane_state *exynos_state)
+static void exynos_plane_mode_set(struct exynos_drm_plane_state *exynos_state,
+				  const struct exynos_drm_plane_config *config)
 
 {
 	struct drm_plane_state *state = &exynos_state->base;
@@ -85,6 +87,9 @@ static void exynos_plane_mode_set(struct exynos_drm_plane_state *exynos_state)
 	src_w = state->src_w >> 16;
 	src_h = state->src_h >> 16;
 
+	exynos_plane_ipp_setup(exynos_state, config, &src_x, &src_y, &src_w,
+			       &src_h, &crtc_w, &crtc_h);
+
 	/* set ratio */
 	exynos_state->h_ratio = (src_w << 16) / crtc_w;
 	exynos_state->v_ratio = (src_h << 16) / crtc_h;
@@ -163,6 +168,13 @@ static void exynos_drm_plane_destroy_state(struct drm_plane *plane,
 {
 	struct exynos_drm_plane_state *old_exynos_state =
 					to_exynos_plane_state(old_state);
+	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
+	/*
+	 * This is the only place in the code, where all temporary objects
+	 * used for processing are no longer used and can be freed.
+	 */
+	exynos_plane_ipp_cleanup(exynos_plane, old_exynos_state);
+
 	__drm_atomic_helper_plane_destroy_state(plane, old_state);
 	kfree(old_exynos_state);
 }
@@ -174,6 +186,7 @@ static struct drm_plane_funcs exynos_plane_funcs = {
 	.reset		= exynos_drm_plane_reset,
 	.atomic_duplicate_state = exynos_drm_plane_duplicate_state,
 	.atomic_destroy_state = exynos_drm_plane_destroy_state,
+	.set_property = drm_atomic_helper_plane_set_property,
 };
 
 static int
@@ -218,16 +231,21 @@ static int exynos_plane_atomic_check(struct drm_plane *plane,
 		return 0;
 
 	/* translate state into exynos_state */
-	exynos_plane_mode_set(exynos_state);
+	exynos_plane_mode_set(exynos_state, exynos_plane->config);
 
 	ret = exynos_drm_plane_check_size(exynos_plane->config, exynos_state);
-	return ret;
+	if (ret)
+		return ret;
+
+	return exynos_plane_ipp_check(exynos_plane, exynos_state);
 }
 
 static void exynos_plane_atomic_update(struct drm_plane *plane,
 				       struct drm_plane_state *old_state)
 {
 	struct drm_plane_state *state = plane->state;
+	struct exynos_drm_plane_state *exynos_state =
+						to_exynos_plane_state(state);
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(state->crtc);
 	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
 
@@ -237,6 +255,8 @@ static void exynos_plane_atomic_update(struct drm_plane *plane,
 	plane->crtc = state->crtc;
 	exynos_plane->pending_fb = state->fb;
 
+	exynos_plane_ipp_update(exynos_plane, exynos_state);
+
 	if (exynos_crtc->ops->update_plane)
 		exynos_crtc->ops->update_plane(exynos_crtc, exynos_plane);
 }
@@ -308,5 +328,5 @@ int exynos_plane_init(struct drm_device *dev,
 		exynos_plane_attach_zpos_property(&exynos_plane->base,
 						  config->zpos);
 
-	return 0;
+	return exynos_plane_ipp_init(dev, exynos_plane);
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_plane_ipp.c
new file mode 100644
index 000000000000..3086fd29f482
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane_ipp.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co.Ltd
+ * Authors: Marek Szyprowski <m.szyprowski@samsung.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.
+ *
+ */
+
+#include <drm/drmP.h>
+
+#include <drm/exynos_drm.h>
+#include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
+#include "exynos_drm_gem.h"
+#include "exynos_drm_ipp.h"
+#include "exynos_drm_plane.h"
+#include "exynos_drm_plane_ipp.h"
+#include "exynos_drm_iommu.h"
+
+static uint32_t preferred_formats[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_NV12,
+};
+
+static uint32_t supported_formats[] = {
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV21,
+	DRM_FORMAT_NV61,
+	DRM_FORMAT_YUV422,
+	DRM_FORMAT_YUV420,
+	DRM_FORMAT_YVU420,
+};
+
+static bool
+exynos_plane_check_format(const struct exynos_drm_plane_config *config,
+			       uint32_t format)
+{
+	int i;
+
+	for (i = 0; i < config->num_pixel_formats; i++)
+		if (config->pixel_formats[i] == format)
+			return true;
+	return false;
+}
+
+static struct drm_framebuffer *exynos_plane_ipp_alloc_fb(struct drm_device *dev,
+					struct exynos_drm_plane_state *state)
+{
+	struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER] = { NULL };
+	struct drm_mode_fb_cmd2 mode_cmd = { 0 };
+	struct drm_framebuffer *fb;
+	unsigned int size;
+	unsigned int flags;
+	int i, cpp;
+	int num_planes = drm_format_num_planes(state->ipp_pixel_format);
+	int ret = 0;
+
+
+	if (is_drm_iommu_supported(dev))
+		flags = EXYNOS_BO_NONCONTIG | EXYNOS_BO_WC;
+	else
+		flags = EXYNOS_BO_CONTIG | EXYNOS_BO_WC;
+
+	mode_cmd.width = state->ipp_dst.x + state->ipp_dst.w;
+	mode_cmd.height = state->ipp_dst.y + state->ipp_dst.h;
+	mode_cmd.pixel_format = state->ipp_pixel_format;
+
+	for (i = 0; i < num_planes; i++) {
+		cpp = drm_format_plane_cpp(state->ipp_pixel_format, i);
+		mode_cmd.pitches[i] = roundup(mode_cmd.width,
+					EXYNOS_DRM_PITCH_ALIGN) * cpp;
+		mode_cmd.offsets[i] = 0;
+		size = mode_cmd.height * mode_cmd.pitches[i];
+		exynos_gem[i] = exynos_drm_gem_create(dev, flags, size);
+		if (IS_ERR(exynos_gem[i])) {
+			ret = PTR_ERR(exynos_gem[i]);
+			goto err_free;
+		}
+	}
+
+	fb = exynos_drm_framebuffer_init(dev, &mode_cmd, exynos_gem, num_planes);
+	if (IS_ERR(fb)) {
+		ret = PTR_ERR(fb);
+		goto err_free;
+	}
+
+	return fb;
+
+err_free:
+	for (;i >= 0; i--)
+		exynos_drm_gem_destroy(exynos_gem[i]);
+	return ERR_PTR(ret);
+}
+
+static bool exynos_plane_ipp_check_fb(struct drm_framebuffer *ipp_fb,
+				struct exynos_drm_plane_state *state)
+{
+	if (state->ipp_dst.x + state->ipp_dst.w <= ipp_fb->width &&
+	    state->ipp_dst.y + state->ipp_dst.h <= ipp_fb->height &&
+	    state->base.fb->pixel_format == ipp_fb->pixel_format)
+		return true;
+	return false;
+}
+
+static int exynos_plane_ipp_transform(struct exynos_drm_plane_state *state)
+{
+	struct drm_framebuffer *src_fb = state->base.fb;
+	struct drm_framebuffer *dst_fb = state->ipp_fb;
+	struct drm_exynos_ipp_config src_config = {
+		.ops_id = EXYNOS_DRM_OPS_SRC,
+		.sz = {
+			.hsize = src_fb->pitches[0] /
+				drm_format_plane_cpp(src_fb->pixel_format, 0),
+			.vsize = src_fb->height,
+		},
+		.fmt = src_fb->pixel_format,
+		.pos = {
+			.x = state->ipp_src.x,
+			.y = state->ipp_src.y,
+			.w = state->ipp_src.w,
+			.h = state->ipp_src.h,
+		},
+	};
+	struct drm_exynos_ipp_config dst_config = {
+		.sz = {
+			.hsize = dst_fb->pitches[0] /
+				drm_format_plane_cpp(dst_fb->pixel_format, 0),
+			.vsize = dst_fb->height,
+		},
+		.fmt = dst_fb->pixel_format,
+		.pos = {
+			.x = state->ipp_dst.x,
+			.y = state->ipp_dst.y,
+			.w = state->ipp_dst.w,
+			.h = state->ipp_dst.h,
+		},
+	};
+	int degree = 0, flip = 0;
+
+	if (state->rotation & BIT(DRM_ROTATE_180))
+		degree = EXYNOS_DRM_DEGREE_180;
+	else if (state->rotation & BIT(DRM_ROTATE_90))
+		degree = EXYNOS_DRM_DEGREE_90;
+	else if (state->rotation & BIT(DRM_ROTATE_270))
+		degree = EXYNOS_DRM_DEGREE_270;
+
+	if (state->rotation & BIT(DRM_REFLECT_X))
+		flip |= EXYNOS_DRM_FLIP_HORIZONTAL;
+	if (state->rotation & BIT(DRM_REFLECT_Y))
+		flip |= EXYNOS_DRM_FLIP_VERTICAL;
+
+	dst_config.flip = flip;
+	dst_config.degree = degree;
+
+	return exynos_ipp_process_internal(src_fb->dev, &src_config, src_fb,
+					   &dst_config, dst_fb);
+}
+
+void exynos_plane_ipp_setup(struct exynos_drm_plane_state *state,
+			    const struct exynos_drm_plane_config *config,
+			    unsigned int *src_x, unsigned int *src_y,
+			    unsigned int *src_w, unsigned int *src_h,
+			    unsigned int *crtc_w, unsigned int *crtc_h)
+{
+	int rotation = state->base.rotation;
+	int pre_x, pre_y, post_x, post_y;
+	int i;
+	bool supported_pixel_format =
+		exynos_plane_check_format(config, state->base.fb->pixel_format);
+
+	state->rotation = rotation;
+
+	/* check if ipp is really needed */
+	if (rotation == BIT(DRM_ROTATE_0) && supported_pixel_format &&
+	    (*src_w == *crtc_w ||
+	     ((config->capabilities & EXYNOS_DRM_PLANE_CAP_DOUBLE) &&
+	       *src_w * 2 == *crtc_w) ||
+	      config->capabilities & EXYNOS_DRM_PLANE_CAP_SCALE) &&
+	    (*src_h == *crtc_h ||
+	     ((config->capabilities & EXYNOS_DRM_PLANE_CAP_DOUBLE) &&
+	       *src_h * 2 == *crtc_h) ||
+	      config->capabilities & EXYNOS_DRM_PLANE_CAP_SCALE))
+		return;
+
+	state->ipp_needed = true;
+
+	state->ipp_pixel_format = state->base.fb->pixel_format;
+	if (!supported_pixel_format) {
+		for (i = 0; i < ARRAY_SIZE(preferred_formats); i++)
+			if (exynos_plane_check_format(config,
+						      preferred_formats[i])) {
+				state->ipp_pixel_format = preferred_formats[i];
+				break;
+			}
+	}
+
+	state->ipp_src.x = rounddown(*src_x, EXYNOS_DRM_PITCH_ALIGN);
+	state->ipp_src.y = rounddown(*src_y, EXYNOS_DRM_PITCH_ALIGN);
+	state->ipp_dst.x = 0;
+	state->ipp_dst.y = 0;
+
+	pre_x = *src_x & (EXYNOS_DRM_PITCH_ALIGN - 1);
+	pre_y = *src_y & (EXYNOS_DRM_PITCH_ALIGN - 1);
+
+	state->ipp_src.w = roundup(*src_w + pre_x, EXYNOS_DRM_PITCH_ALIGN);
+	state->ipp_src.h = roundup(*src_h + pre_y, EXYNOS_DRM_PITCH_ALIGN);
+	if (state->ipp_src.w > state->base.fb->pitches[0])
+		state->ipp_src.w = state->base.fb->pitches[0];
+	if (state->ipp_src.h > state->base.fb->height)
+		state->ipp_src.h = state->base.fb->height;
+
+	state->ipp_dst.w = state->ipp_src.w;
+	state->ipp_dst.h = state->ipp_src.h;
+
+	post_x = state->ipp_src.w - pre_x - *src_w;
+	post_y = state->ipp_src.h - pre_y - *src_h;
+
+	if (rotation & BIT(DRM_REFLECT_Y))
+		swap(pre_y, post_y);
+
+	if (rotation & BIT(DRM_REFLECT_X))
+		swap(pre_x, post_x);
+
+	switch (rotation & 0xf) {
+	case BIT(DRM_ROTATE_0):
+		*src_x = pre_x;
+		*src_y = pre_y;
+		break;
+	case BIT(DRM_ROTATE_90):
+		*src_x = post_y;
+		*src_y = pre_x;
+		swap(*src_w, *src_h);
+		swap(state->ipp_dst.w, state->ipp_dst.h);
+		break;
+	case BIT(DRM_ROTATE_180):
+		*src_x = post_x;
+		*src_y = post_y;
+		break;
+	case BIT(DRM_ROTATE_270):
+		*src_x = pre_y;
+		*src_y = post_x;
+		swap(*src_w, *src_h);
+		swap(state->ipp_dst.w, state->ipp_dst.h);
+		break;
+	}
+
+	/* apply scalling */
+	state->ipp_dst.w = state->ipp_dst.w * *crtc_w / *src_w;
+	state->ipp_dst.h = state->ipp_dst.h * *crtc_h / *src_h;
+
+	*src_x = *src_x * *crtc_w / *src_w;
+	*src_y = *src_y * *crtc_h / *src_h;
+	*src_w = *crtc_w;
+	*src_h = *crtc_h;
+}
+
+int exynos_plane_ipp_check(struct exynos_drm_plane *plane,
+			   struct exynos_drm_plane_state *state)
+{
+	if (!state->ipp_needed)
+		return 0;
+
+	/* check if currently allocated ipp fb can be reused */
+	if (plane->ipp_next_fb &&
+		!exynos_plane_ipp_check_fb(plane->ipp_next_fb, state)) {
+		drm_framebuffer_unreference(plane->ipp_next_fb);
+		plane->ipp_next_fb = NULL;
+	}
+
+	/* allocate new ipp fb */
+	if (!plane->ipp_next_fb) {
+		struct drm_framebuffer *ipp_fb;
+
+		ipp_fb = exynos_plane_ipp_alloc_fb(plane->base.dev, state);
+		if (IS_ERR(ipp_fb))
+			return PTR_ERR(ipp_fb);
+		plane->ipp_next_fb = ipp_fb;
+	}
+
+	state->fb = state->ipp_fb = plane->ipp_next_fb;
+
+	/* perform transformation */
+	return exynos_plane_ipp_transform(state);
+}
+
+void exynos_plane_ipp_update(struct exynos_drm_plane *plane,
+			     struct exynos_drm_plane_state *state)
+{
+	if (!state->ipp_needed)
+		return;
+
+	if (plane->ipp_next_fb)
+		swap(plane->ipp_next_fb, plane->ipp_cur_fb);
+}
+
+void exynos_plane_ipp_cleanup(struct exynos_drm_plane *plane,
+			      struct exynos_drm_plane_state *old_state)
+{
+	struct exynos_drm_plane_state *state;
+
+	/* get current plane state */
+	state = to_exynos_plane_state(plane->base.state);
+
+	if (!state->ipp_needed) {
+		if (plane->ipp_cur_fb) {
+			drm_framebuffer_unreference(plane->ipp_cur_fb);
+			plane->ipp_cur_fb = NULL;
+		}
+		if (plane->ipp_next_fb) {
+			drm_framebuffer_unreference(plane->ipp_next_fb);
+			plane->ipp_next_fb = NULL;
+		}
+	}
+}
+
+int exynos_plane_ipp_init(struct drm_device *dev,
+			  struct exynos_drm_plane *plane)
+{
+	int i, j, num_formats, ipp_formats = 0;
+	uint32_t *formats;
+
+	for (i = 0; i < ARRAY_SIZE(supported_formats); i++)
+		if (!exynos_plane_check_format(plane->config,
+					       supported_formats[i]))
+			ipp_formats++;
+
+	num_formats = plane->config->num_pixel_formats + ipp_formats;
+	formats = kmalloc_array(num_formats, sizeof(uint32_t), GFP_KERNEL);
+	if (!formats)
+		return -ENOMEM;
+
+	memcpy(formats, plane->config->pixel_formats,
+	       plane->config->num_pixel_formats * sizeof(uint32_t));
+	j = plane->config->num_pixel_formats;
+
+	for (i = 0; i < ARRAY_SIZE(supported_formats); i++)
+		if (!exynos_plane_check_format(plane->config,
+					       supported_formats[i]))
+			formats[j++] = supported_formats[i];
+
+	kfree(plane->base.format_types);
+	plane->base.format_types = formats;
+	plane->base.format_count = num_formats;
+
+	if (!dev->mode_config.rotation_property)
+		dev->mode_config.rotation_property =
+			drm_mode_create_rotation_property(dev,
+				BIT(DRM_ROTATE_0) | BIT(DRM_ROTATE_90) |
+				BIT(DRM_ROTATE_180) | BIT(DRM_ROTATE_270) |
+				BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y));
+
+	if (dev->mode_config.rotation_property)
+		drm_object_attach_property(&plane->base.base,
+					   dev->mode_config.rotation_property,
+					   BIT(DRM_ROTATE_0));
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane_ipp.h b/drivers/gpu/drm/exynos/exynos_drm_plane_ipp.h
new file mode 100644
index 000000000000..44b7f2c53829
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane_ipp.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co.Ltd
+ * Authors: Marek Szyprowski <m.szyprowski@samsung.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 _EXYNOS_DRM_PLANE_IPP_H_
+#define _EXYNOS_DRM_PLANE_IPP_H_
+
+#ifdef CONFIG_DRM_EXYNOS_PLANE_IPP
+
+void exynos_plane_ipp_setup(struct exynos_drm_plane_state *state,
+			    const struct exynos_drm_plane_config *config,
+			    unsigned int *src_x, unsigned int *src_y,
+			    unsigned int *src_w, unsigned int *src_h,
+			    unsigned int *crtc_w, unsigned int *crtc_h);
+
+int exynos_plane_ipp_check(struct exynos_drm_plane *plane,
+			   struct exynos_drm_plane_state *state);
+
+void exynos_plane_ipp_update(struct exynos_drm_plane *plane,
+			     struct exynos_drm_plane_state *state);
+
+void exynos_plane_ipp_cleanup(struct exynos_drm_plane *plane,
+			      struct exynos_drm_plane_state *old_state);
+
+int exynos_plane_ipp_init(struct drm_device *dev,
+			  struct exynos_drm_plane *plane);
+
+#else
+
+static inline
+void exynos_plane_ipp_setup(struct exynos_drm_plane_state *state,
+			    const struct exynos_drm_plane_config *config,
+			    unsigned int *src_x, unsigned int *src_y,
+			    unsigned int *src_w, unsigned int *src_h,
+			    unsigned int *crtc_w, unsigned int *crtc_h)
+{
+}
+
+static inline
+int exynos_plane_ipp_check(struct exynos_drm_plane *plane,
+			   struct exynos_drm_plane_state *state)
+{
+	return 0;
+}
+
+static inline
+void exynos_plane_ipp_update(struct exynos_drm_plane *plane,
+			     struct exynos_drm_plane_state *state)
+{
+}
+
+static inline
+void exynos_plane_ipp_cleanup(struct exynos_drm_plane *plane,
+			      struct exynos_drm_plane_state *old_state)
+{
+}
+
+static inline
+int exynos_plane_ipp_init(struct drm_device *dev,
+			  struct exynos_drm_plane *plane)
+{
+	return 0;
+}
+
+#endif
+#endif
-- 
1.9.2

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

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

* Re: [PATCH v2 14/22] drm/exynos: fimd: fix dma burst size setting for small plane size
  2015-11-30 13:53 ` [PATCH v2 14/22] drm/exynos: fimd: fix dma burst size setting for small plane size Marek Szyprowski
@ 2015-11-30 15:40   ` Daniel Stone
  2015-12-10 11:35   ` Inki Dae
  1 sibling, 0 replies; 40+ messages in thread
From: Daniel Stone @ 2015-11-30 15:40 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Krzysztof Kozlowski, linux-samsung-soc,
	Bartlomiej Zolnierkiewicz, Seung-Woo Kim, dri-devel,
	Andrzej Hajda, Javier Martinez Canillas, Tobias Jakobi

Hi,

On 30 November 2015 at 13:53, Marek Szyprowski <m.szyprowski@samsung.com> wrote:
> This patch fixes trashed display of buffers cropped to very small width.
> Even if DMA is unstable and causes tearing when changing the burst size,
> it is still better than displaying a garbage.
>
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>

Reviewed-by: Daniel Stone <daniels@collabora.com>

Cheers,
Daniel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 03/22] drm/exynos: gsc: add device tree support and remove usage of static mappings
  2015-11-30 13:53 ` [PATCH v2 03/22] drm/exynos: gsc: add device tree support and remove usage of static mappings Marek Szyprowski
@ 2015-12-10  6:48   ` Inki Dae
  2015-12-10  6:55     ` Krzysztof Kozlowski
  0 siblings, 1 reply; 40+ messages in thread
From: Inki Dae @ 2015-12-10  6:48 UTC (permalink / raw)
  To: Marek Szyprowski, dri-devel, linux-samsung-soc
  Cc: Joonyoung Shim, Seung-Woo Kim, Andrzej Hajda,
	Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz, Tobias Jakobi,
	Gustavo Padovan, Javier Martinez Canillas, Kukjin Kim

CCing Mr. Kukjin and Krzysztof


Hi Kukjin and Krzysztof,

Below patch includes dt binding about gsc device but it'd be nice this patch to exynos drm tree with others.
So could you give me Acked-by so that I can merge it to exynos drm tree?

Thanks,
Inki Dae

2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
> From: Seung-Woo Kim <sw0312.kim@samsung.com>
> 
> This patch adds device tree support for exynos_drm_gsc. This patch
> also fixed build issue on non-Exynos platforms, thus dependency on
> !ARCH_MULTIPLATFORM can be now removed. The driver cannot be used
> simultaneously with V4L2 Mem2Mem GScaller driver thought.
> 
> Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> [updated commit message, removed the need for wb-lcd property, because
> all gscallers have support for lcd writeback, replaced dependency on
> !ARCH_MULTIPLATFORM with !VIDEO_SAMSUNG_EXYNOS_GSC]
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  .../devicetree/bindings/media/exynos5-gsc.txt      |  4 +++
>  drivers/gpu/drm/exynos/Kconfig                     |  2 +-
>  drivers/gpu/drm/exynos/exynos_drm_gsc.c            | 30 +++++++++++++++++++---
>  drivers/gpu/drm/exynos/regs-gsc.h                  |  4 +--
>  4 files changed, 33 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/media/exynos5-gsc.txt b/Documentation/devicetree/bindings/media/exynos5-gsc.txt
> index 0604d42f38d1..5fe9372abb37 100644
> --- a/Documentation/devicetree/bindings/media/exynos5-gsc.txt
> +++ b/Documentation/devicetree/bindings/media/exynos5-gsc.txt
> @@ -7,6 +7,10 @@ Required properties:
>  - reg: should contain G-Scaler physical address location and length.
>  - interrupts: should contain G-Scaler interrupt number
>  
> +Optional properties:
> +- samsung,sysreg: handle to syscon used to control the system registers to
> +  set writeback input and destination
> +
>  Example:
>  
>  gsc_0:  gsc@0x13e00000 {
> diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
> index 96e86cf4455b..83efca941388 100644
> --- a/drivers/gpu/drm/exynos/Kconfig
> +++ b/drivers/gpu/drm/exynos/Kconfig
> @@ -118,7 +118,7 @@ config DRM_EXYNOS_ROTATOR
>  
>  config DRM_EXYNOS_GSC
>  	bool "GScaler"
> -	depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !ARCH_MULTIPLATFORM
> +	depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !VIDEO_SAMSUNG_EXYNOS_GSC
>  	help
>  	  Choose this option if you want to use Exynos GSC for DRM.
>  
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
> index ed55d37b6330..7aecd23cfa11 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
> @@ -15,7 +15,8 @@
>  #include <linux/platform_device.h>
>  #include <linux/clk.h>
>  #include <linux/pm_runtime.h>
> -#include <plat/map-base.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
>  
>  #include <drm/drmP.h>
>  #include <drm/exynos_drm.h>
> @@ -126,6 +127,7 @@ struct gsc_capability {
>   * @ippdrv: prepare initialization using ippdrv.
>   * @regs_res: register resources.
>   * @regs: memory mapped io registers.
> + * @sysreg: handle to SYSREG block regmap.
>   * @lock: locking of operations.
>   * @gsc_clk: gsc gate clock.
>   * @sc: scaler infomations.
> @@ -138,6 +140,7 @@ struct gsc_context {
>  	struct exynos_drm_ippdrv	ippdrv;
>  	struct resource	*regs_res;
>  	void __iomem	*regs;
> +	struct regmap	*sysreg;
>  	struct mutex	lock;
>  	struct clk	*gsc_clk;
>  	struct gsc_scaler	sc;
> @@ -437,9 +440,12 @@ static int gsc_sw_reset(struct gsc_context *ctx)
>  
>  static void gsc_set_gscblk_fimd_wb(struct gsc_context *ctx, bool enable)
>  {
> -	u32 gscblk_cfg;
> +	unsigned int gscblk_cfg;
>  
> -	gscblk_cfg = readl(SYSREG_GSCBLK_CFG1);
> +	if (!ctx->sysreg)
> +		return;
> +
> +	regmap_read(ctx->sysreg, SYSREG_GSCBLK_CFG1, &gscblk_cfg);
>  
>  	if (enable)
>  		gscblk_cfg |= GSC_BLK_DISP1WB_DEST(ctx->id) |
> @@ -448,7 +454,7 @@ static void gsc_set_gscblk_fimd_wb(struct gsc_context *ctx, bool enable)
>  	else
>  		gscblk_cfg |= GSC_BLK_PXLASYNC_LO_MASK_WB(ctx->id);
>  
> -	writel(gscblk_cfg, SYSREG_GSCBLK_CFG1);
> +	regmap_write(ctx->sysreg, SYSREG_GSCBLK_CFG1, gscblk_cfg);
>  }
>  
>  static void gsc_handle_irq(struct gsc_context *ctx, bool enable,
> @@ -1663,6 +1669,15 @@ static int gsc_probe(struct platform_device *pdev)
>  	if (!ctx)
>  		return -ENOMEM;
>  
> +	if (dev->of_node) {
> +		ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
> +							"samsung,sysreg");
> +		if (IS_ERR(ctx->sysreg)) {
> +			dev_warn(dev, "failed to get system register.\n");
> +			ctx->sysreg = NULL;
> +		}
> +	}
> +
>  	/* clock control */
>  	ctx->gsc_clk = devm_clk_get(dev, "gscl");
>  	if (IS_ERR(ctx->gsc_clk)) {
> @@ -1796,6 +1811,12 @@ static const struct dev_pm_ops gsc_pm_ops = {
>  	SET_RUNTIME_PM_OPS(gsc_runtime_suspend, gsc_runtime_resume, NULL)
>  };
>  
> +static const struct of_device_id exynos_drm_gsc_of_match[] = {
> +	{ .compatible = "samsung,exynos5-gsc" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, exynos_drm_gsc_of_match);
> +
>  struct platform_driver gsc_driver = {
>  	.probe		= gsc_probe,
>  	.remove		= gsc_remove,
> @@ -1803,6 +1824,7 @@ struct platform_driver gsc_driver = {
>  		.name	= "exynos-drm-gsc",
>  		.owner	= THIS_MODULE,
>  		.pm	= &gsc_pm_ops,
> +		.of_match_table = of_match_ptr(exynos_drm_gsc_of_match),
>  	},
>  };
>  
> diff --git a/drivers/gpu/drm/exynos/regs-gsc.h b/drivers/gpu/drm/exynos/regs-gsc.h
> index 9ad592707aaf..4704a993cbb7 100644
> --- a/drivers/gpu/drm/exynos/regs-gsc.h
> +++ b/drivers/gpu/drm/exynos/regs-gsc.h
> @@ -273,12 +273,12 @@
>  #define GSC_CLK_GATE_MODE_SNOOP_CNT(x)	((x) << 0)
>  
>  /* SYSCON. GSCBLK_CFG */
> -#define SYSREG_GSCBLK_CFG1		(S3C_VA_SYS + 0x0224)
> +#define SYSREG_GSCBLK_CFG1		0x0224
>  #define GSC_BLK_DISP1WB_DEST(x)		(x << 10)
>  #define GSC_BLK_SW_RESET_WB_DEST(x)	(1 << (18 + x))
>  #define GSC_BLK_PXLASYNC_LO_MASK_WB(x)	(0 << (14 + x))
>  #define GSC_BLK_GSCL_WB_IN_SRC_SEL(x)	(1 << (2 * x))
> -#define SYSREG_GSCBLK_CFG2		(S3C_VA_SYS + 0x2000)
> +#define SYSREG_GSCBLK_CFG2		0x2000
>  #define PXLASYNC_LO_MASK_CAMIF_GSCL(x)	(1 << (x))
>  
>  #endif /* EXYNOS_REGS_GSC_H_ */
> 

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

* Re: [PATCH v2 03/22] drm/exynos: gsc: add device tree support and remove usage of static mappings
  2015-12-10  6:48   ` Inki Dae
@ 2015-12-10  6:55     ` Krzysztof Kozlowski
  0 siblings, 0 replies; 40+ messages in thread
From: Krzysztof Kozlowski @ 2015-12-10  6:55 UTC (permalink / raw)
  To: Inki Dae, Marek Szyprowski, dri-devel, linux-samsung-soc
  Cc: Joonyoung Shim, Seung-Woo Kim, Andrzej Hajda,
	Bartlomiej Zolnierkiewicz, Tobias Jakobi, Gustavo Padovan,
	Javier Martinez Canillas, Kukjin Kim

On 10.12.2015 15:48, Inki Dae wrote:
> CCing Mr. Kukjin and Krzysztof
> 
> 
> Hi Kukjin and Krzysztof,
> 
> Below patch includes dt binding about gsc device but it'd be nice this patch to exynos drm tree with others.
> So could you give me Acked-by so that I can merge it to exynos drm tree?
> 
> Thanks,
> Inki Dae
> 
> 2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
>> From: Seung-Woo Kim <sw0312.kim@samsung.com>
>>
>> This patch adds device tree support for exynos_drm_gsc. This patch
>> also fixed build issue on non-Exynos platforms, thus dependency on
>> !ARCH_MULTIPLATFORM can be now removed. The driver cannot be used
>> simultaneously with V4L2 Mem2Mem GScaller driver thought.
>>
>> Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
>> [updated commit message, removed the need for wb-lcd property, because
>> all gscallers have support for lcd writeback, replaced dependency on
>> !ARCH_MULTIPLATFORM with !VIDEO_SAMSUNG_EXYNOS_GSC]
>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>> ---
>>  .../devicetree/bindings/media/exynos5-gsc.txt      |  4 +++
>>  drivers/gpu/drm/exynos/Kconfig                     |  2 +-
>>  drivers/gpu/drm/exynos/exynos_drm_gsc.c            | 30 +++++++++++++++++++---
>>  drivers/gpu/drm/exynos/regs-gsc.h                  |  4 +--
>>  4 files changed, 33 insertions(+), 7 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/media/exynos5-gsc.txt b/Documentation/devicetree/bindings/media/exynos5-gsc.txt
>> index 0604d42f38d1..5fe9372abb37 100644
>> --- a/Documentation/devicetree/bindings/media/exynos5-gsc.txt
>> +++ b/Documentation/devicetree/bindings/media/exynos5-gsc.txt
>> @@ -7,6 +7,10 @@ Required properties:
>>  - reg: should contain G-Scaler physical address location and length.
>>  - interrupts: should contain G-Scaler interrupt number
>>  
>> +Optional properties:
>> +- samsung,sysreg: handle to syscon used to control the system registers to
>> +  set writeback input and destination
>> +
>>  Example:
>>  
>>  gsc_0:  gsc@0x13e00000 {


Acked-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>

Best regards,
Krzysztof

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

* Re: [PATCH v2 14/22] drm/exynos: fimd: fix dma burst size setting for small plane size
  2015-11-30 13:53 ` [PATCH v2 14/22] drm/exynos: fimd: fix dma burst size setting for small plane size Marek Szyprowski
  2015-11-30 15:40   ` Daniel Stone
@ 2015-12-10 11:35   ` Inki Dae
  2015-12-10 12:59     ` Marek Szyprowski
  1 sibling, 1 reply; 40+ messages in thread
From: Inki Dae @ 2015-12-10 11:35 UTC (permalink / raw)
  To: Marek Szyprowski, dri-devel, linux-samsung-soc
  Cc: Javier Martinez Canillas, Krzysztof Kozlowski, Tobias Jakobi,
	Bartlomiej Zolnierkiewicz, Seung-Woo Kim, Andrzej Hajda

Hi Marek,

2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
> This patch fixes trashed display of buffers cropped to very small width.
> Even if DMA is unstable and causes tearing when changing the burst size,
> it is still better than displaying a garbage.

It seems that this patch is different from above description. I think below patch is just cleanup,
which passes each member necessary instead of passing a drm_framebuffer object.

Thanks,
Inki Dae

> 
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c | 24 +++++++++++-------------
>  1 file changed, 11 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> index 70cd2681e343..2e2247126581 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> @@ -487,7 +487,7 @@ static void fimd_commit(struct exynos_drm_crtc *crtc)
>  
>  
>  static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
> -				struct drm_framebuffer *fb)
> +				uint32_t pixel_format, int width)
>  {
>  	unsigned long val;
>  
> @@ -498,11 +498,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
>  	 * So the request format is ARGB8888 then change it to XRGB8888.
>  	 */
>  	if (ctx->driver_data->has_limited_fmt && !win) {
> -		if (fb->pixel_format == DRM_FORMAT_ARGB8888)
> -			fb->pixel_format = DRM_FORMAT_XRGB8888;
> +		if (pixel_format == DRM_FORMAT_ARGB8888)
> +			pixel_format = DRM_FORMAT_XRGB8888;
>  	}
>  
> -	switch (fb->pixel_format) {
> +	switch (pixel_format) {
>  	case DRM_FORMAT_C8:
>  		val |= WINCON0_BPPMODE_8BPP_PALETTE;
>  		val |= WINCONx_BURSTLEN_8WORD;
> @@ -538,17 +538,15 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
>  		break;
>  	}
>  
> -	DRM_DEBUG_KMS("bpp = %d\n", fb->bits_per_pixel);
> -
>  	/*
> -	 * In case of exynos, setting dma-burst to 16Word causes permanent
> -	 * tearing for very small buffers, e.g. cursor buffer. Burst Mode
> -	 * switching which is based on plane size is not recommended as
> -	 * plane size varies alot towards the end of the screen and rapid
> -	 * movement causes unstable DMA which results into iommu crash/tear.
> +	 * Setting dma-burst to 16Word causes permanent tearing for very small
> +	 * buffers, e.g. cursor buffer. Burst Mode switching which based on
> +	 * plane size is not recommended as plane size varies alot towards the
> +	 * end of the screen and rapid movement causes unstable DMA, but it is
> +	 * still better to change dma-burst than displaying garbage.
>  	 */
>  
> -	if (fb->width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
> +	if (width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
>  		val &= ~WINCONx_BURSTLEN_MASK;
>  		val |= WINCONx_BURSTLEN_4WORD;
>  	}
> @@ -723,7 +721,7 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
>  		DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
>  	}
>  
> -	fimd_win_set_pixfmt(ctx, win, fb);
> +	fimd_win_set_pixfmt(ctx, win, fb->pixel_format, state->src.w);
>  
>  	/* hardware window 0 doesn't support color key. */
>  	if (win != 0)
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 10/22] drm/exynos: introduce exynos_drm_plane_config structure
  2015-11-30 13:53 ` [PATCH v2 10/22] drm/exynos: introduce exynos_drm_plane_config structure Marek Szyprowski
@ 2015-12-10 11:47   ` Inki Dae
  0 siblings, 0 replies; 40+ messages in thread
From: Inki Dae @ 2015-12-10 11:47 UTC (permalink / raw)
  To: Marek Szyprowski, dri-devel, linux-samsung-soc
  Cc: Joonyoung Shim, Seung-Woo Kim, Andrzej Hajda,
	Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz, Tobias Jakobi,
	Gustavo Padovan, Javier Martinez Canillas

Hi Marek,

2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
> This patch adds common structure for keeping plane configuration and
> capabilities data. This patch is inspired by similar code developed by
> Tobias Jakobi.
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 18 ++++++++---
>  drivers/gpu/drm/exynos/exynos7_drm_decon.c    | 23 +++++++++-----
>  drivers/gpu/drm/exynos/exynos_drm_drv.h       | 19 ++++++++++++
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 25 ++++++++++-----
>  drivers/gpu/drm/exynos/exynos_drm_plane.c     | 34 +++++++++------------
>  drivers/gpu/drm/exynos/exynos_drm_plane.h     |  7 ++---
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 25 ++++++++++-----
>  drivers/gpu/drm/exynos/exynos_mixer.c         | 44 +++++++++++++++------------
>  8 files changed, 121 insertions(+), 74 deletions(-)
> 
<--snip-->
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> index 3ce141236fad..90701647aef1 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> @@ -30,7 +30,6 @@
>  
>  /* vidi has totally three virtual windows. */
>  #define WINDOWS_NR		3
> -#define CURSOR_WIN		2
>  
>  #define ctx_from_connector(c)	container_of(c, struct vidi_context, \
>  					connector)
> @@ -90,6 +89,12 @@ static const uint32_t formats[] = {
>  	DRM_FORMAT_NV12,
>  };
>  
> +static const enum drm_plane_type vidi_win_types[WINDOWS_NR] = {
> +	DRM_PLANE_TYPE_PRIMARY,
> +	DRM_PLANE_TYPE_OVERLAY,
> +	DRM_PLANE_TYPE_CURSOR,
> +};
> +
>  static int vidi_enable_vblank(struct exynos_drm_crtc *crtc)
>  {
>  	struct vidi_context *ctx = crtc->ctx;
> @@ -442,17 +447,21 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
>  	struct drm_device *drm_dev = data;
>  	struct drm_encoder *encoder = &ctx->encoder;
>  	struct exynos_drm_plane *exynos_plane;
> -	enum drm_plane_type type;
> -	unsigned int zpos;
> +	struct exynos_drm_plane_config plane_config = { 0 };
> +	unsigned int i;
>  	int pipe, ret;
>  
>  	vidi_ctx_initialize(ctx, drm_dev);
>  
> -	for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
> -		type = exynos_plane_get_type(zpos, CURSOR_WIN);
> -		ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
> -					1 << ctx->pipe, type, formats,
> -					ARRAY_SIZE(formats), zpos);
> +	plane_config.pixel_formats = formats;
> +	plane_config.num_pixel_formats = ARRAY_SIZE(formats);
> +
> +	for (i = 0; i < WINDOWS_NR; i++) {
> +		plane_config.zpos = i;
> +		plane_config.type = vidi_win_types(i);

vidi_win_types is not really a function. So this should be 'vidi_win_type[i]'
This is a trivial so I can fix it.

Thanks,
Inki Dae

> +
> +		ret = exynos_plane_init(drm_dev, &ctx->planes[i],
> +					1 << ctx->pipe, &plane_config);
>  		if (ret)
>  			return ret;
>  	}
> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
> index 8d2ce13eb725..a229f86d221a 100644
> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
> @@ -43,7 +43,6 @@
>  
>  #define MIXER_WIN_NR		3
>  #define VP_DEFAULT_WIN		2
> -#define CURSOR_WIN		1
>  
>  /* The pixelformats that are natively supported by the mixer. */
>  #define MXR_FORMAT_RGB565	4
> @@ -112,6 +111,25 @@ struct mixer_drv_data {
>  	bool					has_sclk;
>  };
>  
> +static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
> +	{
> +		.zpos = 0,
> +		.type = DRM_PLANE_TYPE_PRIMARY,
> +		.pixel_formats = mixer_formats,
> +		.num_pixel_formats = ARRAY_SIZE(mixer_formats),
> +	}, {
> +		.zpos = 1,
> +		.type = DRM_PLANE_TYPE_CURSOR,
> +		.pixel_formats = mixer_formats,
> +		.num_pixel_formats = ARRAY_SIZE(mixer_formats),
> +	}, {
> +		.zpos = 2,
> +		.type = DRM_PLANE_TYPE_OVERLAY,
> +		.pixel_formats = vp_formats,
> +		.num_pixel_formats = ARRAY_SIZE(vp_formats),
> +	},
> +};
> +
>  static const u8 filter_y_horiz_tap8[] = {
>  	0,	-1,	-1,	-1,	-1,	-1,	-1,	-1,
>  	-1,	-1,	-1,	-1,	-1,	0,	0,	0,
> @@ -1155,33 +1173,19 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
>  	struct mixer_context *ctx = dev_get_drvdata(dev);
>  	struct drm_device *drm_dev = data;
>  	struct exynos_drm_plane *exynos_plane;
> -	unsigned int zpos;
> +	unsigned int i;
>  	int ret;
>  
>  	ret = mixer_initialize(ctx, drm_dev);
>  	if (ret)
>  		return ret;
>  
> -	for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) {
> -		enum drm_plane_type type;
> -		const uint32_t *formats;
> -		unsigned int fcount;
> -
> -		if (zpos == VP_DEFAULT_WIN && !ctx->vp_enabled)
> +	for (i = 0; i < MIXER_WIN_NR; i++) {
> +		if (i == VP_DEFAULT_WIN && !ctx->vp_enabled)
>  			continue;
>  
> -		if (zpos < VP_DEFAULT_WIN) {
> -			formats = mixer_formats;
> -			fcount = ARRAY_SIZE(mixer_formats);
> -		} else {
> -			formats = vp_formats;
> -			fcount = ARRAY_SIZE(vp_formats);
> -		}
> -
> -		type = exynos_plane_get_type(zpos, CURSOR_WIN);
> -		ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
> -					1 << ctx->pipe, type, formats, fcount,
> -					zpos);
> +		ret = exynos_plane_init(drm_dev, &ctx->planes[i],
> +					1 << ctx->pipe, &plane_configs[i]);
>  		if (ret)
>  			return ret;
>  	}
> 

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

* Re: [PATCH v2 14/22] drm/exynos: fimd: fix dma burst size setting for small plane size
  2015-12-10 11:35   ` Inki Dae
@ 2015-12-10 12:59     ` Marek Szyprowski
  2015-12-10 15:36       ` Daniel Stone
  2015-12-11  9:04       ` Inki Dae
  0 siblings, 2 replies; 40+ messages in thread
From: Marek Szyprowski @ 2015-12-10 12:59 UTC (permalink / raw)
  To: Inki Dae, dri-devel, linux-samsung-soc
  Cc: Joonyoung Shim, Seung-Woo Kim, Andrzej Hajda,
	Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz, Tobias Jakobi,
	Gustavo Padovan, Javier Martinez Canillas

Hello,

On 2015-12-10 12:35, Inki Dae wrote:
> Hi Marek,
>
> 2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
>> This patch fixes trashed display of buffers cropped to very small width.
>> Even if DMA is unstable and causes tearing when changing the burst size,
>> it is still better than displaying a garbage.
> It seems that this patch is different from above description. I think below patch is just cleanup,
> which passes each member necessary instead of passing a drm_framebuffer object.

Please note the last chunk of this patch. After applying it width is
taken from state->src.w instead of fb->width. If you want, I can split
this patch into 2 parts - one cleanup without functional change, and
second, replacement of fb->width with state->src.w.


>
>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>> ---
>>   drivers/gpu/drm/exynos/exynos_drm_fimd.c | 24 +++++++++++-------------
>>   1 file changed, 11 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>> index 70cd2681e343..2e2247126581 100644
>> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>> @@ -487,7 +487,7 @@ static void fimd_commit(struct exynos_drm_crtc *crtc)
>>   
>>   
>>   static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
>> -				struct drm_framebuffer *fb)
>> +				uint32_t pixel_format, int width)
>>   {
>>   	unsigned long val;
>>   
>> @@ -498,11 +498,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
>>   	 * So the request format is ARGB8888 then change it to XRGB8888.
>>   	 */
>>   	if (ctx->driver_data->has_limited_fmt && !win) {
>> -		if (fb->pixel_format == DRM_FORMAT_ARGB8888)
>> -			fb->pixel_format = DRM_FORMAT_XRGB8888;
>> +		if (pixel_format == DRM_FORMAT_ARGB8888)
>> +			pixel_format = DRM_FORMAT_XRGB8888;
>>   	}
>>   
>> -	switch (fb->pixel_format) {
>> +	switch (pixel_format) {
>>   	case DRM_FORMAT_C8:
>>   		val |= WINCON0_BPPMODE_8BPP_PALETTE;
>>   		val |= WINCONx_BURSTLEN_8WORD;
>> @@ -538,17 +538,15 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
>>   		break;
>>   	}
>>   
>> -	DRM_DEBUG_KMS("bpp = %d\n", fb->bits_per_pixel);
>> -
>>   	/*
>> -	 * In case of exynos, setting dma-burst to 16Word causes permanent
>> -	 * tearing for very small buffers, e.g. cursor buffer. Burst Mode
>> -	 * switching which is based on plane size is not recommended as
>> -	 * plane size varies alot towards the end of the screen and rapid
>> -	 * movement causes unstable DMA which results into iommu crash/tear.
>> +	 * Setting dma-burst to 16Word causes permanent tearing for very small
>> +	 * buffers, e.g. cursor buffer. Burst Mode switching which based on
>> +	 * plane size is not recommended as plane size varies alot towards the
>> +	 * end of the screen and rapid movement causes unstable DMA, but it is
>> +	 * still better to change dma-burst than displaying garbage.
>>   	 */
>>   
>> -	if (fb->width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
>> +	if (width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
>>   		val &= ~WINCONx_BURSTLEN_MASK;
>>   		val |= WINCONx_BURSTLEN_4WORD;
>>   	}
>> @@ -723,7 +721,7 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
>>   		DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
>>   	}
>>   
>> -	fimd_win_set_pixfmt(ctx, win, fb);
>> +	fimd_win_set_pixfmt(ctx, win, fb->pixel_format, state->src.w);
>>   
>>   	/* hardware window 0 doesn't support color key. */
>>   	if (win != 0)
>>

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

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

* Re: [PATCH v2 06/22] drm/exynos: move dma_addr attribute from exynos plane to exynos fb
  2015-11-30 13:53 ` [PATCH v2 06/22] drm/exynos: move dma_addr attribute from exynos plane to exynos fb Marek Szyprowski
@ 2015-12-10 13:05   ` Inki Dae
  2015-12-11  9:02     ` Inki Dae
  0 siblings, 1 reply; 40+ messages in thread
From: Inki Dae @ 2015-12-10 13:05 UTC (permalink / raw)
  To: Marek Szyprowski, dri-devel, linux-samsung-soc
  Cc: Joonyoung Shim, Seung-Woo Kim, Andrzej Hajda,
	Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz, Tobias Jakobi,
	Gustavo Padovan, Javier Martinez Canillas



2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
> DMA address is a framebuffer attribute and the right place for it is
> exynos_drm_framebuffer not exynos_drm_plane. This patch also introduces
> helper function for getting dma address of the given framebuffer.
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> ---
>  drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 13 ++++++++-----
>  drivers/gpu/drm/exynos/exynos7_drm_decon.c    | 16 +++++++++-------
>  drivers/gpu/drm/exynos/exynos_drm_drv.h       |  3 ---
>  drivers/gpu/drm/exynos/exynos_drm_fb.c        | 16 ++++++----------
>  drivers/gpu/drm/exynos/exynos_drm_fb.h        |  3 +--
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 10 ++++++----
>  drivers/gpu/drm/exynos/exynos_drm_plane.c     | 18 ------------------
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c      |  5 ++++-
>  drivers/gpu/drm/exynos/exynos_mixer.c         |  7 ++++---
>  9 files changed, 38 insertions(+), 53 deletions(-)
> 

<--snip-->

> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> index 669362c53f49..3ce141236fad 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> @@ -24,6 +24,7 @@
>  
>  #include "exynos_drm_drv.h"
>  #include "exynos_drm_crtc.h"
> +#include "exynos_drm_fb.h"
>  #include "exynos_drm_plane.h"
>  #include "exynos_drm_vidi.h"
>  
> @@ -126,11 +127,13 @@ static void vidi_update_plane(struct exynos_drm_crtc *crtc,
>  			      struct exynos_drm_plane *plane)
>  {
>  	struct vidi_context *ctx = crtc->ctx;
> +	dma_addr_t addr;
>  
>  	if (ctx->suspended)
>  		return;
>  
> -	DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
> +	addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);

At this point, plane->base.fb is NULL so null pointer access happens like below,

[    5.969422] Unable to handle kernel NULL pointer dereference at virtual address 00000090
[    5.977481] pgd = ee590000
[    5.980142] [00000090] *pgd=6e526831, *pte=00000000, *ppte=00000000
[    5.986347] Internal error: Oops: 17 [#1] PREEMPT SMP ARM
[    5.991712] Modules linked in:
[    5.994770] CPU: 3 PID: 1598 Comm: sh Not tainted 4.4.0-rc3-00052-gc60d7e2-dirty #199
[    6.002565] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[    6.008647] task: ef328000 ti: ee4d4000 task.ti: ee4d4000
[    6.014053] PC is at exynos_drm_fb_dma_addr+0x8/0x14
[    6.018990] LR is at vidi_update_plane+0x4c/0xc4
[    6.023581] pc : [<c02b1fb4>]    lr : [<c02c3cc4>]    psr: 80000013
[    6.023581] sp : ee4d5d90  ip : 00000001  fp : 00000000
[    6.035029] r10: 00000000  r9 : c05b965c  r8 : ee813e00
[    6.040241] r7 : 00000000  r6 : ee8e3330  r5 : 00000000  r4 : ee8e3010
[    6.046749] r3 : 00000000  r2 : 00000000  r1 : 00000024  r0 : 00000000
[    6.053264] Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[    6.060379] Control: 10c5387d  Table: 6e59004a  DAC: 00000051
[    6.066107] Process sh (pid: 1598, stack limit = 0xee4d4210)
[    6.071748] Stack: (0xee4d5d90 to 0xee4d6000)
[    6.076100] 5d80:                                     00000000 ee813300 ee476e40 00000005
[    6.084236] 5da0: ee8e3330 c028ac14 00000008 ee476e40 ee476fc0 ef3b3800 ee476fc0 eeb3e380
[    6.092395] 5dc0: 00000002 c02b08e4 00000000 eeb3e3a4 ee476fc0 ee476e40 ef3b3800 eeb3e380
[    6.100554] 5de0: 00000002 c02b12b8 ee854400 00000000 00000001 ee8501a8 00000000 ee476e40
[    6.108714] 5e00: ef3b3800 00000001 ee476e40 00000050 ee850c80 00000001 ee476e40 ef3b3aac
[    6.116873] 5e20: 00000002 000000ff 00000000 c028e0ec 000a82b4 c02acc50 ee8e36a0 ee476c80
[    6.125032] 5e40: ef3b3aac ef3b3800 ee476c9c ee850c80 ef3b3800 ef3b3800 ef3b3800 ef3b398c
[    6.133191] 5e60: c088c390 00000002 000a82b4 c028f8d4 00000000 ef3b3800 ef0f4300 c028f948
[    6.141350] 5e80: ee850c80 c028f864 ef3b3a84 00000001 ef3b3a90 c02853e4 00000001 00000000
[    6.149509] 5ea0: 000a82b4 ee4d5ec0 00000002 ee8e3010 00000002 00000002 ee4d5f88 00000000
[    6.157669] 5ec0: 00000000 eeb8df00 000a82b4 c02c4278 00000002 ee476b00 eeb8df0c c01390ac
[    6.165828] 5ee0: 00000000 00000000 ee4e1f00 00000002 000a9540 ee4d5f88 c000f844 ee4d4000
[    6.173987] 5f00: 00000000 c00dbf70 000a82b4 c00093dc ee4d4000 ee4d5f78 ef328234 c0579bec
[    6.182146] 5f20: 00000001 00000001 ee4d5f3c 00000001 ee45e9c4 00000001 000a82b4 c005ca74
[    6.190306] 5f40: ee45e9c4 00000002 000a9540 c005cad4 ee4e1f00 00000002 000a9540 ee4d5f88
[    6.198465] 5f60: c000f844 c00dc770 00000000 00000000 ee4e1f00 ee4e1f00 00000002 000a9540
[    6.206624] 5f80: c000f844 c00dcf98 00000000 00000000 00000003 000a7c40 00000001 000a9540
[    6.214783] 5fa0: 00000004 c000f680 000a7c40 00000001 00000001 000a9540 00000002 00000000
[    6.222942] 5fc0: 000a7c40 00000001 000a9540 00000004 00000020 000a82c8 000a8294 000a82b4
[    6.231102] 5fe0: 00000000 be8b1624 00012345 b6e94166 40000030 00000001 00000000 00000000
[    6.239270] [<c02b1fb4>] (exynos_drm_fb_dma_addr) from [<c02c3cc4>] (vidi_update_plane+0x4c/0xc4)
[    6.248122] [<c02c3cc4>] (vidi_update_plane) from [<c028ac14>] (drm_atomic_helper_commit_planes+0x1f4/0x258)
[    6.257928] [<c028ac14>] (drm_atomic_helper_commit_planes) from [<c02b08e4>] (exynos_atomic_commit_complete+0xe4/0x1c4)
[    6.268688] [<c02b08e4>] (exynos_atomic_commit_complete) from [<c02b12b8>] (exynos_atomic_commit+0x180/0x1cc)
[    6.278584] [<c02b12b8>] (exynos_atomic_commit) from [<c028e0ec>] (restore_fbdev_mode+0x260/0x290)
[    6.287525] [<c028e0ec>] (restore_fbdev_mode) from [<c028f8d4>] (drm_fb_helper_restore_fbdev_mode_unlocked+0x30/0x74)
[    6.298111] [<c028f8d4>] (drm_fb_helper_restore_fbdev_mode_unlocked) from [<c028f948>] (drm_fb_helper_set_par+0x30/0x54)
[    6.308961] [<c028f948>] (drm_fb_helper_set_par) from [<c028f864>] (drm_fb_helper_hotplug_event+0x9c/0xdc)
[    6.318595] [<c028f864>] (drm_fb_helper_hotplug_event) from [<c02853e4>] (drm_helper_hpd_irq_event+0xd4/0x160)
[    6.328578] [<c02853e4>] (drm_helper_hpd_irq_event) from [<c02c4278>] (vidi_store_connection+0x94/0xcc)
[    6.337954] [<c02c4278>] (vidi_store_connection) from [<c01390ac>] (kernfs_fop_write+0xb8/0x1bc)
[    6.346723] [<c01390ac>] (kernfs_fop_write) from [<c00dbf70>] (__vfs_write+0x20/0xd8)
[    6.354531] [<c00dbf70>] (__vfs_write) from [<c00dc770>] (vfs_write+0x90/0x164)
[    6.361821] [<c00dc770>] (vfs_write) from [<c00dcf98>] (SyS_write+0x44/0x9c)
[    6.368855] [<c00dcf98>] (SyS_write) from [<c000f680>] (ret_fast_syscall+0x0/0x3c)
[    6.376404] Code: eb0b17f1 eaffffe7 e3510003 d2811024 (d7900101) 

When vidi driver is intiated by triggering a connection sysfs file, vidi driver tries modeset binding by calling drm_fb_helper_hotplug_event.
However, at this time it seems there is a case that plan->state->crtc exists but plane->fb is NULL, which would be related to vidi driver.

I just looked into this issue roughly so we would need to check this issue in more details.

Thanks,
Inki Dae

> +	DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>  
>  	if (ctx->vblank_on)
>  		schedule_work(&ctx->work);
> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
> index 47777be1a754..f40de82848dc 100644
> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
> @@ -37,6 +37,7 @@
>  
>  #include "exynos_drm_drv.h"
>  #include "exynos_drm_crtc.h"
> +#include "exynos_drm_fb.h"
>  #include "exynos_drm_plane.h"
>  #include "exynos_drm_iommu.h"
>  
> @@ -422,8 +423,8 @@ static void vp_video_buffer(struct mixer_context *ctx,
>  		return;
>  	}
>  
> -	luma_addr[0] = plane->dma_addr[0];
> -	chroma_addr[0] = plane->dma_addr[1];
> +	luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
> +	chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
>  
>  	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
>  		ctx->interlace = true;
> @@ -575,7 +576,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
>  	dst_y_offset = plane->crtc_y;
>  
>  	/* converting dma address base and source offset */
> -	dma_addr = plane->dma_addr[0]
> +	dma_addr = exynos_drm_fb_dma_addr(fb, 0)
>  		+ (plane->src_x * fb->bits_per_pixel >> 3)
>  		+ (plane->src_y * fb->pitches[0]);
>  	src_x_offset = 0;
> 

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

* Re: [PATCH v2 14/22] drm/exynos: fimd: fix dma burst size setting for small plane size
  2015-12-10 12:59     ` Marek Szyprowski
@ 2015-12-10 15:36       ` Daniel Stone
  2015-12-11  9:04       ` Inki Dae
  1 sibling, 0 replies; 40+ messages in thread
From: Daniel Stone @ 2015-12-10 15:36 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Inki Dae, dri-devel, linux-samsung-soc, Javier Martinez Canillas,
	Krzysztof Kozlowski, Tobias Jakobi, Bartlomiej Zolnierkiewicz,
	Seung-Woo Kim, Andrzej Hajda

Hi Inki,

On 10 December 2015 at 12:59, Marek Szyprowski <m.szyprowski@samsung.com> wrote:
> On 2015-12-10 12:35, Inki Dae wrote:
>> 2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
>>> This patch fixes trashed display of buffers cropped to very small width.
>>> Even if DMA is unstable and causes tearing when changing the burst size,
>>> it is still better than displaying a garbage.
>>
>> It seems that this patch is different from above description. I think
>> below patch is just cleanup,
>> which passes each member necessary instead of passing a drm_framebuffer
>> object.
>
>
> Please note the last chunk of this patch. After applying it width is
> taken from state->src.w instead of fb->width. If you want, I can split
> this patch into 2 parts - one cleanup without functional change, and
> second, replacement of fb->width with state->src.w.

As Marek says:
http://lists.freedesktop.org/archives/dri-devel/2015-November/094321.html

It fixes the case where state->src.w (what we're actually scanning
out) < MIN_FB_WIDTH_FOR_16WORD_BURST < fb->width (total size of
allocated buffer). Quite subtle, but also correct.

Cheers,
Daniel

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

* Re: [PATCH v2 06/22] drm/exynos: move dma_addr attribute from exynos plane to exynos fb
  2015-12-10 13:05   ` Inki Dae
@ 2015-12-11  9:02     ` Inki Dae
  2015-12-11  9:26       ` Marek Szyprowski
  0 siblings, 1 reply; 40+ messages in thread
From: Inki Dae @ 2015-12-11  9:02 UTC (permalink / raw)
  To: Marek Szyprowski, dri-devel, linux-samsung-soc
  Cc: Javier Martinez Canillas, Krzysztof Kozlowski, Tobias Jakobi,
	Bartlomiej Zolnierkiewicz, Seung-Woo Kim, Andrzej Hajda

Hi Marek,

I found out why NULL point access happened. That was incurred by below your patch,
[PATCH] drm/exynos: move dma_addr attribute from exynos plane to exynos fb

When another crtc driver is hotplugged in runtime such as HDMI or VIDI,
the drm frambuffer object of fb_helper is set to the plane state of the new crtc driver
so the driver should get the drm framebuffer object from the plane's state or
exynos_plane->pending_fb which is set by exynos_plane_atomic_update function.

After that, I think the drm framebuffer should be set to drm plane as a current fb
which would be scanned out.

Anyway, I can fix it like below if you are ok.

Thanks,
Inki Dae

--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -137,7 +137,7 @@ static void vidi_update_plane(struct exynos_drm_crtc *crtc,
        if (ctx->suspended)
                return;
 
-       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
+       addr = exynos_drm_fb_dma_addr(plane->pending_fb, 0);
        DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);

+	plane->base.fb = plane->pending_fb;
 
        if (ctx->vblank_on)


2015년 12월 10일 22:05에 Inki Dae 이(가) 쓴 글:
> 
> 
> 2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
>> DMA address is a framebuffer attribute and the right place for it is
>> exynos_drm_framebuffer not exynos_drm_plane. This patch also introduces
>> helper function for getting dma address of the given framebuffer.
>>
>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>> Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>> ---
>>  drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 13 ++++++++-----
>>  drivers/gpu/drm/exynos/exynos7_drm_decon.c    | 16 +++++++++-------
>>  drivers/gpu/drm/exynos/exynos_drm_drv.h       |  3 ---
>>  drivers/gpu/drm/exynos/exynos_drm_fb.c        | 16 ++++++----------
>>  drivers/gpu/drm/exynos/exynos_drm_fb.h        |  3 +--
>>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 10 ++++++----
>>  drivers/gpu/drm/exynos/exynos_drm_plane.c     | 18 ------------------
>>  drivers/gpu/drm/exynos/exynos_drm_vidi.c      |  5 ++++-
>>  drivers/gpu/drm/exynos/exynos_mixer.c         |  7 ++++---
>>  9 files changed, 38 insertions(+), 53 deletions(-)
>>
> 
> <--snip-->
> 
>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>> index 669362c53f49..3ce141236fad 100644
>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>> @@ -24,6 +24,7 @@
>>  
>>  #include "exynos_drm_drv.h"
>>  #include "exynos_drm_crtc.h"
>> +#include "exynos_drm_fb.h"
>>  #include "exynos_drm_plane.h"
>>  #include "exynos_drm_vidi.h"
>>  
>> @@ -126,11 +127,13 @@ static void vidi_update_plane(struct exynos_drm_crtc *crtc,
>>  			      struct exynos_drm_plane *plane)
>>  {
>>  	struct vidi_context *ctx = crtc->ctx;
>> +	dma_addr_t addr;
>>  
>>  	if (ctx->suspended)
>>  		return;
>>  
>> -	DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
>> +	addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
> 
> At this point, plane->base.fb is NULL so null pointer access happens like below,
> 
> [    5.969422] Unable to handle kernel NULL pointer dereference at virtual address 00000090
> [    5.977481] pgd = ee590000
> [    5.980142] [00000090] *pgd=6e526831, *pte=00000000, *ppte=00000000
> [    5.986347] Internal error: Oops: 17 [#1] PREEMPT SMP ARM
> [    5.991712] Modules linked in:
> [    5.994770] CPU: 3 PID: 1598 Comm: sh Not tainted 4.4.0-rc3-00052-gc60d7e2-dirty #199
> [    6.002565] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [    6.008647] task: ef328000 ti: ee4d4000 task.ti: ee4d4000
> [    6.014053] PC is at exynos_drm_fb_dma_addr+0x8/0x14
> [    6.018990] LR is at vidi_update_plane+0x4c/0xc4
> [    6.023581] pc : [<c02b1fb4>]    lr : [<c02c3cc4>]    psr: 80000013
> [    6.023581] sp : ee4d5d90  ip : 00000001  fp : 00000000
> [    6.035029] r10: 00000000  r9 : c05b965c  r8 : ee813e00
> [    6.040241] r7 : 00000000  r6 : ee8e3330  r5 : 00000000  r4 : ee8e3010
> [    6.046749] r3 : 00000000  r2 : 00000000  r1 : 00000024  r0 : 00000000
> [    6.053264] Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
> [    6.060379] Control: 10c5387d  Table: 6e59004a  DAC: 00000051
> [    6.066107] Process sh (pid: 1598, stack limit = 0xee4d4210)
> [    6.071748] Stack: (0xee4d5d90 to 0xee4d6000)
> [    6.076100] 5d80:                                     00000000 ee813300 ee476e40 00000005
> [    6.084236] 5da0: ee8e3330 c028ac14 00000008 ee476e40 ee476fc0 ef3b3800 ee476fc0 eeb3e380
> [    6.092395] 5dc0: 00000002 c02b08e4 00000000 eeb3e3a4 ee476fc0 ee476e40 ef3b3800 eeb3e380
> [    6.100554] 5de0: 00000002 c02b12b8 ee854400 00000000 00000001 ee8501a8 00000000 ee476e40
> [    6.108714] 5e00: ef3b3800 00000001 ee476e40 00000050 ee850c80 00000001 ee476e40 ef3b3aac
> [    6.116873] 5e20: 00000002 000000ff 00000000 c028e0ec 000a82b4 c02acc50 ee8e36a0 ee476c80
> [    6.125032] 5e40: ef3b3aac ef3b3800 ee476c9c ee850c80 ef3b3800 ef3b3800 ef3b3800 ef3b398c
> [    6.133191] 5e60: c088c390 00000002 000a82b4 c028f8d4 00000000 ef3b3800 ef0f4300 c028f948
> [    6.141350] 5e80: ee850c80 c028f864 ef3b3a84 00000001 ef3b3a90 c02853e4 00000001 00000000
> [    6.149509] 5ea0: 000a82b4 ee4d5ec0 00000002 ee8e3010 00000002 00000002 ee4d5f88 00000000
> [    6.157669] 5ec0: 00000000 eeb8df00 000a82b4 c02c4278 00000002 ee476b00 eeb8df0c c01390ac
> [    6.165828] 5ee0: 00000000 00000000 ee4e1f00 00000002 000a9540 ee4d5f88 c000f844 ee4d4000
> [    6.173987] 5f00: 00000000 c00dbf70 000a82b4 c00093dc ee4d4000 ee4d5f78 ef328234 c0579bec
> [    6.182146] 5f20: 00000001 00000001 ee4d5f3c 00000001 ee45e9c4 00000001 000a82b4 c005ca74
> [    6.190306] 5f40: ee45e9c4 00000002 000a9540 c005cad4 ee4e1f00 00000002 000a9540 ee4d5f88
> [    6.198465] 5f60: c000f844 c00dc770 00000000 00000000 ee4e1f00 ee4e1f00 00000002 000a9540
> [    6.206624] 5f80: c000f844 c00dcf98 00000000 00000000 00000003 000a7c40 00000001 000a9540
> [    6.214783] 5fa0: 00000004 c000f680 000a7c40 00000001 00000001 000a9540 00000002 00000000
> [    6.222942] 5fc0: 000a7c40 00000001 000a9540 00000004 00000020 000a82c8 000a8294 000a82b4
> [    6.231102] 5fe0: 00000000 be8b1624 00012345 b6e94166 40000030 00000001 00000000 00000000
> [    6.239270] [<c02b1fb4>] (exynos_drm_fb_dma_addr) from [<c02c3cc4>] (vidi_update_plane+0x4c/0xc4)
> [    6.248122] [<c02c3cc4>] (vidi_update_plane) from [<c028ac14>] (drm_atomic_helper_commit_planes+0x1f4/0x258)
> [    6.257928] [<c028ac14>] (drm_atomic_helper_commit_planes) from [<c02b08e4>] (exynos_atomic_commit_complete+0xe4/0x1c4)
> [    6.268688] [<c02b08e4>] (exynos_atomic_commit_complete) from [<c02b12b8>] (exynos_atomic_commit+0x180/0x1cc)
> [    6.278584] [<c02b12b8>] (exynos_atomic_commit) from [<c028e0ec>] (restore_fbdev_mode+0x260/0x290)
> [    6.287525] [<c028e0ec>] (restore_fbdev_mode) from [<c028f8d4>] (drm_fb_helper_restore_fbdev_mode_unlocked+0x30/0x74)
> [    6.298111] [<c028f8d4>] (drm_fb_helper_restore_fbdev_mode_unlocked) from [<c028f948>] (drm_fb_helper_set_par+0x30/0x54)
> [    6.308961] [<c028f948>] (drm_fb_helper_set_par) from [<c028f864>] (drm_fb_helper_hotplug_event+0x9c/0xdc)
> [    6.318595] [<c028f864>] (drm_fb_helper_hotplug_event) from [<c02853e4>] (drm_helper_hpd_irq_event+0xd4/0x160)
> [    6.328578] [<c02853e4>] (drm_helper_hpd_irq_event) from [<c02c4278>] (vidi_store_connection+0x94/0xcc)
> [    6.337954] [<c02c4278>] (vidi_store_connection) from [<c01390ac>] (kernfs_fop_write+0xb8/0x1bc)
> [    6.346723] [<c01390ac>] (kernfs_fop_write) from [<c00dbf70>] (__vfs_write+0x20/0xd8)
> [    6.354531] [<c00dbf70>] (__vfs_write) from [<c00dc770>] (vfs_write+0x90/0x164)
> [    6.361821] [<c00dc770>] (vfs_write) from [<c00dcf98>] (SyS_write+0x44/0x9c)
> [    6.368855] [<c00dcf98>] (SyS_write) from [<c000f680>] (ret_fast_syscall+0x0/0x3c)
> [    6.376404] Code: eb0b17f1 eaffffe7 e3510003 d2811024 (d7900101) 
> 
> When vidi driver is intiated by triggering a connection sysfs file, vidi driver tries modeset binding by calling drm_fb_helper_hotplug_event.
> However, at this time it seems there is a case that plan->state->crtc exists but plane->fb is NULL, which would be related to vidi driver.
> 
> I just looked into this issue roughly so we would need to check this issue in more details.
> 
> Thanks,
> Inki Dae
> 
>> +	DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>  
>>  	if (ctx->vblank_on)
>>  		schedule_work(&ctx->work);
>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
>> index 47777be1a754..f40de82848dc 100644
>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
>> @@ -37,6 +37,7 @@
>>  
>>  #include "exynos_drm_drv.h"
>>  #include "exynos_drm_crtc.h"
>> +#include "exynos_drm_fb.h"
>>  #include "exynos_drm_plane.h"
>>  #include "exynos_drm_iommu.h"
>>  
>> @@ -422,8 +423,8 @@ static void vp_video_buffer(struct mixer_context *ctx,
>>  		return;
>>  	}
>>  
>> -	luma_addr[0] = plane->dma_addr[0];
>> -	chroma_addr[0] = plane->dma_addr[1];
>> +	luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
>> +	chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
>>  
>>  	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
>>  		ctx->interlace = true;
>> @@ -575,7 +576,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
>>  	dst_y_offset = plane->crtc_y;
>>  
>>  	/* converting dma address base and source offset */
>> -	dma_addr = plane->dma_addr[0]
>> +	dma_addr = exynos_drm_fb_dma_addr(fb, 0)
>>  		+ (plane->src_x * fb->bits_per_pixel >> 3)
>>  		+ (plane->src_y * fb->pitches[0]);
>>  	src_x_offset = 0;
>>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 14/22] drm/exynos: fimd: fix dma burst size setting for small plane size
  2015-12-10 12:59     ` Marek Szyprowski
  2015-12-10 15:36       ` Daniel Stone
@ 2015-12-11  9:04       ` Inki Dae
  1 sibling, 0 replies; 40+ messages in thread
From: Inki Dae @ 2015-12-11  9:04 UTC (permalink / raw)
  To: Marek Szyprowski, dri-devel, linux-samsung-soc
  Cc: Joonyoung Shim, Seung-Woo Kim, Andrzej Hajda,
	Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz, Tobias Jakobi,
	Gustavo Padovan, Javier Martinez Canillas



2015년 12월 10일 21:59에 Marek Szyprowski 이(가) 쓴 글:
> Hello,
> 
> On 2015-12-10 12:35, Inki Dae wrote:
>> Hi Marek,
>>
>> 2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
>>> This patch fixes trashed display of buffers cropped to very small width.
>>> Even if DMA is unstable and causes tearing when changing the burst size,
>>> it is still better than displaying a garbage.
>> It seems that this patch is different from above description. I think below patch is just cleanup,
>> which passes each member necessary instead of passing a drm_framebuffer object.
> 
> Please note the last chunk of this patch. After applying it width is
> taken from state->src.w instead of fb->width. If you want, I can split
> this patch into 2 parts - one cleanup without functional change, and
> second, replacement of fb->width with state->src.w.

Will just merge it.

Thanks,
Inki Dae

> 
> 
>>
>>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>>> ---
>>>   drivers/gpu/drm/exynos/exynos_drm_fimd.c | 24 +++++++++++-------------
>>>   1 file changed, 11 insertions(+), 13 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>>> index 70cd2681e343..2e2247126581 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>>> @@ -487,7 +487,7 @@ static void fimd_commit(struct exynos_drm_crtc *crtc)
>>>       static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
>>> -                struct drm_framebuffer *fb)
>>> +                uint32_t pixel_format, int width)
>>>   {
>>>       unsigned long val;
>>>   @@ -498,11 +498,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
>>>        * So the request format is ARGB8888 then change it to XRGB8888.
>>>        */
>>>       if (ctx->driver_data->has_limited_fmt && !win) {
>>> -        if (fb->pixel_format == DRM_FORMAT_ARGB8888)
>>> -            fb->pixel_format = DRM_FORMAT_XRGB8888;
>>> +        if (pixel_format == DRM_FORMAT_ARGB8888)
>>> +            pixel_format = DRM_FORMAT_XRGB8888;
>>>       }
>>>   -    switch (fb->pixel_format) {
>>> +    switch (pixel_format) {
>>>       case DRM_FORMAT_C8:
>>>           val |= WINCON0_BPPMODE_8BPP_PALETTE;
>>>           val |= WINCONx_BURSTLEN_8WORD;
>>> @@ -538,17 +538,15 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
>>>           break;
>>>       }
>>>   -    DRM_DEBUG_KMS("bpp = %d\n", fb->bits_per_pixel);
>>> -
>>>       /*
>>> -     * In case of exynos, setting dma-burst to 16Word causes permanent
>>> -     * tearing for very small buffers, e.g. cursor buffer. Burst Mode
>>> -     * switching which is based on plane size is not recommended as
>>> -     * plane size varies alot towards the end of the screen and rapid
>>> -     * movement causes unstable DMA which results into iommu crash/tear.
>>> +     * Setting dma-burst to 16Word causes permanent tearing for very small
>>> +     * buffers, e.g. cursor buffer. Burst Mode switching which based on
>>> +     * plane size is not recommended as plane size varies alot towards the
>>> +     * end of the screen and rapid movement causes unstable DMA, but it is
>>> +     * still better to change dma-burst than displaying garbage.
>>>        */
>>>   -    if (fb->width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
>>> +    if (width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
>>>           val &= ~WINCONx_BURSTLEN_MASK;
>>>           val |= WINCONx_BURSTLEN_4WORD;
>>>       }
>>> @@ -723,7 +721,7 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
>>>           DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
>>>       }
>>>   -    fimd_win_set_pixfmt(ctx, win, fb);
>>> +    fimd_win_set_pixfmt(ctx, win, fb->pixel_format, state->src.w);
>>>         /* hardware window 0 doesn't support color key. */
>>>       if (win != 0)
>>>
> 
> Best regards

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

* Re: [PATCH v2 06/22] drm/exynos: move dma_addr attribute from exynos plane to exynos fb
  2015-12-11  9:02     ` Inki Dae
@ 2015-12-11  9:26       ` Marek Szyprowski
  2015-12-11  9:57         ` Inki Dae
  0 siblings, 1 reply; 40+ messages in thread
From: Marek Szyprowski @ 2015-12-11  9:26 UTC (permalink / raw)
  To: Inki Dae, dri-devel, linux-samsung-soc
  Cc: Javier Martinez Canillas, Krzysztof Kozlowski, Tobias Jakobi,
	Bartlomiej Zolnierkiewicz, Seung-Woo Kim, Andrzej Hajda

Hi Inki,

On 2015-12-11 10:02, Inki Dae wrote:
> Hi Marek,
>
> I found out why NULL point access happened. That was incurred by below your patch,
> [PATCH] drm/exynos: move dma_addr attribute from exynos plane to exynos fb
>
> When another crtc driver is hotplugged in runtime such as HDMI or VIDI,
> the drm frambuffer object of fb_helper is set to the plane state of the new crtc driver
> so the driver should get the drm framebuffer object from the plane's state or
> exynos_plane->pending_fb which is set by exynos_plane_atomic_update function.
>
> After that, I think the drm framebuffer should be set to drm plane as a current fb
> which would be scanned out.
>
> Anyway, I can fix it like below if you are ok.
>
> Thanks,
> Inki Dae
>
> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> @@ -137,7 +137,7 @@ static void vidi_update_plane(struct exynos_drm_crtc *crtc,
>          if (ctx->suspended)
>                  return;
>   
> -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
> +       addr = exynos_drm_fb_dma_addr(plane->pending_fb, 0);
>          DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>
> +	plane->base.fb = plane->pending_fb;

plane->base.fb should not be modified. I think that the following fix is 
more
appropriate:
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -132,12 +132,13 @@ static void vidi_update_plane(struct 
exynos_drm_crtc *crtc,
                               struct exynos_drm_plane *plane)
  {
         struct vidi_context *ctx = crtc->ctx;
-       dma_addr_t addr;
+       dma_addr_t addr = 0;

         if (ctx->suspended)
                 return;

-       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
+       if (plane->base.fb)
+               addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
         DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);

         if (ctx->vblank_on)

I will investigate the case of NULL plane->state.fb, because it might be 
relevant
to other crtc drivers as well.


>   
>          if (ctx->vblank_on)
>
>
> 2015년 12월 10일 22:05에 Inki Dae 이(가) 쓴 글:
>>
>> 2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
>>> DMA address is a framebuffer attribute and the right place for it is
>>> exynos_drm_framebuffer not exynos_drm_plane. This patch also introduces
>>> helper function for getting dma address of the given framebuffer.
>>>
>>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>>> Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>>> ---
>>>   drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 13 ++++++++-----
>>>   drivers/gpu/drm/exynos/exynos7_drm_decon.c    | 16 +++++++++-------
>>>   drivers/gpu/drm/exynos/exynos_drm_drv.h       |  3 ---
>>>   drivers/gpu/drm/exynos/exynos_drm_fb.c        | 16 ++++++----------
>>>   drivers/gpu/drm/exynos/exynos_drm_fb.h        |  3 +--
>>>   drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 10 ++++++----
>>>   drivers/gpu/drm/exynos/exynos_drm_plane.c     | 18 ------------------
>>>   drivers/gpu/drm/exynos/exynos_drm_vidi.c      |  5 ++++-
>>>   drivers/gpu/drm/exynos/exynos_mixer.c         |  7 ++++---
>>>   9 files changed, 38 insertions(+), 53 deletions(-)
>>>
>> <--snip-->
>>
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>> index 669362c53f49..3ce141236fad 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>> @@ -24,6 +24,7 @@
>>>   
>>>   #include "exynos_drm_drv.h"
>>>   #include "exynos_drm_crtc.h"
>>> +#include "exynos_drm_fb.h"
>>>   #include "exynos_drm_plane.h"
>>>   #include "exynos_drm_vidi.h"
>>>   
>>> @@ -126,11 +127,13 @@ static void vidi_update_plane(struct exynos_drm_crtc *crtc,
>>>   			      struct exynos_drm_plane *plane)
>>>   {
>>>   	struct vidi_context *ctx = crtc->ctx;
>>> +	dma_addr_t addr;
>>>   
>>>   	if (ctx->suspended)
>>>   		return;
>>>   
>>> -	DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
>>> +	addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>> At this point, plane->base.fb is NULL so null pointer access happens like below,
>>
>> [    5.969422] Unable to handle kernel NULL pointer dereference at virtual address 00000090
>> [    5.977481] pgd = ee590000
>> [    5.980142] [00000090] *pgd=6e526831, *pte=00000000, *ppte=00000000
>> [    5.986347] Internal error: Oops: 17 [#1] PREEMPT SMP ARM
>> [    5.991712] Modules linked in:
>> [    5.994770] CPU: 3 PID: 1598 Comm: sh Not tainted 4.4.0-rc3-00052-gc60d7e2-dirty #199
>> [    6.002565] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
>> [    6.008647] task: ef328000 ti: ee4d4000 task.ti: ee4d4000
>> [    6.014053] PC is at exynos_drm_fb_dma_addr+0x8/0x14
>> [    6.018990] LR is at vidi_update_plane+0x4c/0xc4
>> [    6.023581] pc : [<c02b1fb4>]    lr : [<c02c3cc4>]    psr: 80000013
>> [    6.023581] sp : ee4d5d90  ip : 00000001  fp : 00000000
>> [    6.035029] r10: 00000000  r9 : c05b965c  r8 : ee813e00
>> [    6.040241] r7 : 00000000  r6 : ee8e3330  r5 : 00000000  r4 : ee8e3010
>> [    6.046749] r3 : 00000000  r2 : 00000000  r1 : 00000024  r0 : 00000000
>> [    6.053264] Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
>> [    6.060379] Control: 10c5387d  Table: 6e59004a  DAC: 00000051
>> [    6.066107] Process sh (pid: 1598, stack limit = 0xee4d4210)
>> [    6.071748] Stack: (0xee4d5d90 to 0xee4d6000)
>> [    6.076100] 5d80:                                     00000000 ee813300 ee476e40 00000005
>> [    6.084236] 5da0: ee8e3330 c028ac14 00000008 ee476e40 ee476fc0 ef3b3800 ee476fc0 eeb3e380
>> [    6.092395] 5dc0: 00000002 c02b08e4 00000000 eeb3e3a4 ee476fc0 ee476e40 ef3b3800 eeb3e380
>> [    6.100554] 5de0: 00000002 c02b12b8 ee854400 00000000 00000001 ee8501a8 00000000 ee476e40
>> [    6.108714] 5e00: ef3b3800 00000001 ee476e40 00000050 ee850c80 00000001 ee476e40 ef3b3aac
>> [    6.116873] 5e20: 00000002 000000ff 00000000 c028e0ec 000a82b4 c02acc50 ee8e36a0 ee476c80
>> [    6.125032] 5e40: ef3b3aac ef3b3800 ee476c9c ee850c80 ef3b3800 ef3b3800 ef3b3800 ef3b398c
>> [    6.133191] 5e60: c088c390 00000002 000a82b4 c028f8d4 00000000 ef3b3800 ef0f4300 c028f948
>> [    6.141350] 5e80: ee850c80 c028f864 ef3b3a84 00000001 ef3b3a90 c02853e4 00000001 00000000
>> [    6.149509] 5ea0: 000a82b4 ee4d5ec0 00000002 ee8e3010 00000002 00000002 ee4d5f88 00000000
>> [    6.157669] 5ec0: 00000000 eeb8df00 000a82b4 c02c4278 00000002 ee476b00 eeb8df0c c01390ac
>> [    6.165828] 5ee0: 00000000 00000000 ee4e1f00 00000002 000a9540 ee4d5f88 c000f844 ee4d4000
>> [    6.173987] 5f00: 00000000 c00dbf70 000a82b4 c00093dc ee4d4000 ee4d5f78 ef328234 c0579bec
>> [    6.182146] 5f20: 00000001 00000001 ee4d5f3c 00000001 ee45e9c4 00000001 000a82b4 c005ca74
>> [    6.190306] 5f40: ee45e9c4 00000002 000a9540 c005cad4 ee4e1f00 00000002 000a9540 ee4d5f88
>> [    6.198465] 5f60: c000f844 c00dc770 00000000 00000000 ee4e1f00 ee4e1f00 00000002 000a9540
>> [    6.206624] 5f80: c000f844 c00dcf98 00000000 00000000 00000003 000a7c40 00000001 000a9540
>> [    6.214783] 5fa0: 00000004 c000f680 000a7c40 00000001 00000001 000a9540 00000002 00000000
>> [    6.222942] 5fc0: 000a7c40 00000001 000a9540 00000004 00000020 000a82c8 000a8294 000a82b4
>> [    6.231102] 5fe0: 00000000 be8b1624 00012345 b6e94166 40000030 00000001 00000000 00000000
>> [    6.239270] [<c02b1fb4>] (exynos_drm_fb_dma_addr) from [<c02c3cc4>] (vidi_update_plane+0x4c/0xc4)
>> [    6.248122] [<c02c3cc4>] (vidi_update_plane) from [<c028ac14>] (drm_atomic_helper_commit_planes+0x1f4/0x258)
>> [    6.257928] [<c028ac14>] (drm_atomic_helper_commit_planes) from [<c02b08e4>] (exynos_atomic_commit_complete+0xe4/0x1c4)
>> [    6.268688] [<c02b08e4>] (exynos_atomic_commit_complete) from [<c02b12b8>] (exynos_atomic_commit+0x180/0x1cc)
>> [    6.278584] [<c02b12b8>] (exynos_atomic_commit) from [<c028e0ec>] (restore_fbdev_mode+0x260/0x290)
>> [    6.287525] [<c028e0ec>] (restore_fbdev_mode) from [<c028f8d4>] (drm_fb_helper_restore_fbdev_mode_unlocked+0x30/0x74)
>> [    6.298111] [<c028f8d4>] (drm_fb_helper_restore_fbdev_mode_unlocked) from [<c028f948>] (drm_fb_helper_set_par+0x30/0x54)
>> [    6.308961] [<c028f948>] (drm_fb_helper_set_par) from [<c028f864>] (drm_fb_helper_hotplug_event+0x9c/0xdc)
>> [    6.318595] [<c028f864>] (drm_fb_helper_hotplug_event) from [<c02853e4>] (drm_helper_hpd_irq_event+0xd4/0x160)
>> [    6.328578] [<c02853e4>] (drm_helper_hpd_irq_event) from [<c02c4278>] (vidi_store_connection+0x94/0xcc)
>> [    6.337954] [<c02c4278>] (vidi_store_connection) from [<c01390ac>] (kernfs_fop_write+0xb8/0x1bc)
>> [    6.346723] [<c01390ac>] (kernfs_fop_write) from [<c00dbf70>] (__vfs_write+0x20/0xd8)
>> [    6.354531] [<c00dbf70>] (__vfs_write) from [<c00dc770>] (vfs_write+0x90/0x164)
>> [    6.361821] [<c00dc770>] (vfs_write) from [<c00dcf98>] (SyS_write+0x44/0x9c)
>> [    6.368855] [<c00dcf98>] (SyS_write) from [<c000f680>] (ret_fast_syscall+0x0/0x3c)
>> [    6.376404] Code: eb0b17f1 eaffffe7 e3510003 d2811024 (d7900101)
>>
>> When vidi driver is intiated by triggering a connection sysfs file, vidi driver tries modeset binding by calling drm_fb_helper_hotplug_event.
>> However, at this time it seems there is a case that plan->state->crtc exists but plane->fb is NULL, which would be related to vidi driver.
>>
>> I just looked into this issue roughly so we would need to check this issue in more details.
>>
>> Thanks,
>> Inki Dae
>>
>>> +	DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>   
>>>   	if (ctx->vblank_on)
>>>   		schedule_work(&ctx->work);
>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
>>> index 47777be1a754..f40de82848dc 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
>>> @@ -37,6 +37,7 @@
>>>   
>>>   #include "exynos_drm_drv.h"
>>>   #include "exynos_drm_crtc.h"
>>> +#include "exynos_drm_fb.h"
>>>   #include "exynos_drm_plane.h"
>>>   #include "exynos_drm_iommu.h"
>>>   
>>> @@ -422,8 +423,8 @@ static void vp_video_buffer(struct mixer_context *ctx,
>>>   		return;
>>>   	}
>>>   
>>> -	luma_addr[0] = plane->dma_addr[0];
>>> -	chroma_addr[0] = plane->dma_addr[1];
>>> +	luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
>>> +	chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
>>>   
>>>   	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
>>>   		ctx->interlace = true;
>>> @@ -575,7 +576,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
>>>   	dst_y_offset = plane->crtc_y;
>>>   
>>>   	/* converting dma address base and source offset */
>>> -	dma_addr = plane->dma_addr[0]
>>> +	dma_addr = exynos_drm_fb_dma_addr(fb, 0)
>>>   		+ (plane->src_x * fb->bits_per_pixel >> 3)
>>>   		+ (plane->src_y * fb->pitches[0]);
>>>   	src_x_offset = 0;
>>>

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

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

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

* Re: [PATCH v2 06/22] drm/exynos: move dma_addr attribute from exynos plane to exynos fb
  2015-12-11  9:26       ` Marek Szyprowski
@ 2015-12-11  9:57         ` Inki Dae
  2015-12-11 11:27           ` Marek Szyprowski
  0 siblings, 1 reply; 40+ messages in thread
From: Inki Dae @ 2015-12-11  9:57 UTC (permalink / raw)
  To: Marek Szyprowski, dri-devel, linux-samsung-soc
  Cc: Javier Martinez Canillas, Krzysztof Kozlowski, Tobias Jakobi,
	Bartlomiej Zolnierkiewicz, Seung-Woo Kim, Andrzej Hajda

Hi Marek,

2015년 12월 11일 18:26에 Marek Szyprowski 이(가) 쓴 글:
> Hi Inki,
> 
> On 2015-12-11 10:02, Inki Dae wrote:
>> Hi Marek,
>>
>> I found out why NULL point access happened. That was incurred by below your patch,
>> [PATCH] drm/exynos: move dma_addr attribute from exynos plane to exynos fb
>>
>> When another crtc driver is hotplugged in runtime such as HDMI or VIDI,
>> the drm frambuffer object of fb_helper is set to the plane state of the new crtc driver
>> so the driver should get the drm framebuffer object from the plane's state or
>> exynos_plane->pending_fb which is set by exynos_plane_atomic_update function.
>>
>> After that, I think the drm framebuffer should be set to drm plane as a current fb
>> which would be scanned out.
>>
>> Anyway, I can fix it like below if you are ok.
>>
>> Thanks,
>> Inki Dae
>>
>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>> @@ -137,7 +137,7 @@ static void vidi_update_plane(struct exynos_drm_crtc *crtc,
>>          if (ctx->suspended)
>>                  return;
>>   -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>> +       addr = exynos_drm_fb_dma_addr(plane->pending_fb, 0);
>>          DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>
>> +    plane->base.fb = plane->pending_fb;
> 
> plane->base.fb should not be modified. I think that the following fix is more

Could you explain why plane->base.fb shouldn't be modified?

In case that userspace requests setplane, plane->base.fb would be updated after update_plane callback.
However, in other cases, I don't see how plane->base.fb could be updated.
In this case, I think vendor specific drivers would need to update it as a current fb to be scanned out like other some drivers did.
Of course, it may be possible for drm core part to take care of it appropriately later.

Thanks,
Inki Dae

> appropriate:
> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> @@ -132,12 +132,13 @@ static void vidi_update_plane(struct exynos_drm_crtc *crtc,
>                               struct exynos_drm_plane *plane)
>  {
>         struct vidi_context *ctx = crtc->ctx;
> -       dma_addr_t addr;
> +       dma_addr_t addr = 0;
> 
>         if (ctx->suspended)
>                 return;
> 
> -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
> +       if (plane->base.fb)
> +               addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>         DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
> 
>         if (ctx->vblank_on)
> 
> I will investigate the case of NULL plane->state.fb, because it might be relevant
> to other crtc drivers as well.
> 
> 
>>            if (ctx->vblank_on)
>>
>>
>> 2015년 12월 10일 22:05에 Inki Dae 이(가) 쓴 글:
>>>
>>> 2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
>>>> DMA address is a framebuffer attribute and the right place for it is
>>>> exynos_drm_framebuffer not exynos_drm_plane. This patch also introduces
>>>> helper function for getting dma address of the given framebuffer.
>>>>
>>>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>>>> Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>>>> ---
>>>>   drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 13 ++++++++-----
>>>>   drivers/gpu/drm/exynos/exynos7_drm_decon.c    | 16 +++++++++-------
>>>>   drivers/gpu/drm/exynos/exynos_drm_drv.h       |  3 ---
>>>>   drivers/gpu/drm/exynos/exynos_drm_fb.c        | 16 ++++++----------
>>>>   drivers/gpu/drm/exynos/exynos_drm_fb.h        |  3 +--
>>>>   drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 10 ++++++----
>>>>   drivers/gpu/drm/exynos/exynos_drm_plane.c     | 18 ------------------
>>>>   drivers/gpu/drm/exynos/exynos_drm_vidi.c      |  5 ++++-
>>>>   drivers/gpu/drm/exynos/exynos_mixer.c         |  7 ++++---
>>>>   9 files changed, 38 insertions(+), 53 deletions(-)
>>>>
>>> <--snip-->
>>>
>>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>> index 669362c53f49..3ce141236fad 100644
>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>> @@ -24,6 +24,7 @@
>>>>     #include "exynos_drm_drv.h"
>>>>   #include "exynos_drm_crtc.h"
>>>> +#include "exynos_drm_fb.h"
>>>>   #include "exynos_drm_plane.h"
>>>>   #include "exynos_drm_vidi.h"
>>>>   @@ -126,11 +127,13 @@ static void vidi_update_plane(struct exynos_drm_crtc *crtc,
>>>>                     struct exynos_drm_plane *plane)
>>>>   {
>>>>       struct vidi_context *ctx = crtc->ctx;
>>>> +    dma_addr_t addr;
>>>>         if (ctx->suspended)
>>>>           return;
>>>>   -    DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
>>>> +    addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>> At this point, plane->base.fb is NULL so null pointer access happens like below,
>>>
>>> [    5.969422] Unable to handle kernel NULL pointer dereference at virtual address 00000090
>>> [    5.977481] pgd = ee590000
>>> [    5.980142] [00000090] *pgd=6e526831, *pte=00000000, *ppte=00000000
>>> [    5.986347] Internal error: Oops: 17 [#1] PREEMPT SMP ARM
>>> [    5.991712] Modules linked in:
>>> [    5.994770] CPU: 3 PID: 1598 Comm: sh Not tainted 4.4.0-rc3-00052-gc60d7e2-dirty #199
>>> [    6.002565] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
>>> [    6.008647] task: ef328000 ti: ee4d4000 task.ti: ee4d4000
>>> [    6.014053] PC is at exynos_drm_fb_dma_addr+0x8/0x14
>>> [    6.018990] LR is at vidi_update_plane+0x4c/0xc4
>>> [    6.023581] pc : [<c02b1fb4>]    lr : [<c02c3cc4>]    psr: 80000013
>>> [    6.023581] sp : ee4d5d90  ip : 00000001  fp : 00000000
>>> [    6.035029] r10: 00000000  r9 : c05b965c  r8 : ee813e00
>>> [    6.040241] r7 : 00000000  r6 : ee8e3330  r5 : 00000000  r4 : ee8e3010
>>> [    6.046749] r3 : 00000000  r2 : 00000000  r1 : 00000024  r0 : 00000000
>>> [    6.053264] Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
>>> [    6.060379] Control: 10c5387d  Table: 6e59004a  DAC: 00000051
>>> [    6.066107] Process sh (pid: 1598, stack limit = 0xee4d4210)
>>> [    6.071748] Stack: (0xee4d5d90 to 0xee4d6000)
>>> [    6.076100] 5d80:                                     00000000 ee813300 ee476e40 00000005
>>> [    6.084236] 5da0: ee8e3330 c028ac14 00000008 ee476e40 ee476fc0 ef3b3800 ee476fc0 eeb3e380
>>> [    6.092395] 5dc0: 00000002 c02b08e4 00000000 eeb3e3a4 ee476fc0 ee476e40 ef3b3800 eeb3e380
>>> [    6.100554] 5de0: 00000002 c02b12b8 ee854400 00000000 00000001 ee8501a8 00000000 ee476e40
>>> [    6.108714] 5e00: ef3b3800 00000001 ee476e40 00000050 ee850c80 00000001 ee476e40 ef3b3aac
>>> [    6.116873] 5e20: 00000002 000000ff 00000000 c028e0ec 000a82b4 c02acc50 ee8e36a0 ee476c80
>>> [    6.125032] 5e40: ef3b3aac ef3b3800 ee476c9c ee850c80 ef3b3800 ef3b3800 ef3b3800 ef3b398c
>>> [    6.133191] 5e60: c088c390 00000002 000a82b4 c028f8d4 00000000 ef3b3800 ef0f4300 c028f948
>>> [    6.141350] 5e80: ee850c80 c028f864 ef3b3a84 00000001 ef3b3a90 c02853e4 00000001 00000000
>>> [    6.149509] 5ea0: 000a82b4 ee4d5ec0 00000002 ee8e3010 00000002 00000002 ee4d5f88 00000000
>>> [    6.157669] 5ec0: 00000000 eeb8df00 000a82b4 c02c4278 00000002 ee476b00 eeb8df0c c01390ac
>>> [    6.165828] 5ee0: 00000000 00000000 ee4e1f00 00000002 000a9540 ee4d5f88 c000f844 ee4d4000
>>> [    6.173987] 5f00: 00000000 c00dbf70 000a82b4 c00093dc ee4d4000 ee4d5f78 ef328234 c0579bec
>>> [    6.182146] 5f20: 00000001 00000001 ee4d5f3c 00000001 ee45e9c4 00000001 000a82b4 c005ca74
>>> [    6.190306] 5f40: ee45e9c4 00000002 000a9540 c005cad4 ee4e1f00 00000002 000a9540 ee4d5f88
>>> [    6.198465] 5f60: c000f844 c00dc770 00000000 00000000 ee4e1f00 ee4e1f00 00000002 000a9540
>>> [    6.206624] 5f80: c000f844 c00dcf98 00000000 00000000 00000003 000a7c40 00000001 000a9540
>>> [    6.214783] 5fa0: 00000004 c000f680 000a7c40 00000001 00000001 000a9540 00000002 00000000
>>> [    6.222942] 5fc0: 000a7c40 00000001 000a9540 00000004 00000020 000a82c8 000a8294 000a82b4
>>> [    6.231102] 5fe0: 00000000 be8b1624 00012345 b6e94166 40000030 00000001 00000000 00000000
>>> [    6.239270] [<c02b1fb4>] (exynos_drm_fb_dma_addr) from [<c02c3cc4>] (vidi_update_plane+0x4c/0xc4)
>>> [    6.248122] [<c02c3cc4>] (vidi_update_plane) from [<c028ac14>] (drm_atomic_helper_commit_planes+0x1f4/0x258)
>>> [    6.257928] [<c028ac14>] (drm_atomic_helper_commit_planes) from [<c02b08e4>] (exynos_atomic_commit_complete+0xe4/0x1c4)
>>> [    6.268688] [<c02b08e4>] (exynos_atomic_commit_complete) from [<c02b12b8>] (exynos_atomic_commit+0x180/0x1cc)
>>> [    6.278584] [<c02b12b8>] (exynos_atomic_commit) from [<c028e0ec>] (restore_fbdev_mode+0x260/0x290)
>>> [    6.287525] [<c028e0ec>] (restore_fbdev_mode) from [<c028f8d4>] (drm_fb_helper_restore_fbdev_mode_unlocked+0x30/0x74)
>>> [    6.298111] [<c028f8d4>] (drm_fb_helper_restore_fbdev_mode_unlocked) from [<c028f948>] (drm_fb_helper_set_par+0x30/0x54)
>>> [    6.308961] [<c028f948>] (drm_fb_helper_set_par) from [<c028f864>] (drm_fb_helper_hotplug_event+0x9c/0xdc)
>>> [    6.318595] [<c028f864>] (drm_fb_helper_hotplug_event) from [<c02853e4>] (drm_helper_hpd_irq_event+0xd4/0x160)
>>> [    6.328578] [<c02853e4>] (drm_helper_hpd_irq_event) from [<c02c4278>] (vidi_store_connection+0x94/0xcc)
>>> [    6.337954] [<c02c4278>] (vidi_store_connection) from [<c01390ac>] (kernfs_fop_write+0xb8/0x1bc)
>>> [    6.346723] [<c01390ac>] (kernfs_fop_write) from [<c00dbf70>] (__vfs_write+0x20/0xd8)
>>> [    6.354531] [<c00dbf70>] (__vfs_write) from [<c00dc770>] (vfs_write+0x90/0x164)
>>> [    6.361821] [<c00dc770>] (vfs_write) from [<c00dcf98>] (SyS_write+0x44/0x9c)
>>> [    6.368855] [<c00dcf98>] (SyS_write) from [<c000f680>] (ret_fast_syscall+0x0/0x3c)
>>> [    6.376404] Code: eb0b17f1 eaffffe7 e3510003 d2811024 (d7900101)
>>>
>>> When vidi driver is intiated by triggering a connection sysfs file, vidi driver tries modeset binding by calling drm_fb_helper_hotplug_event.
>>> However, at this time it seems there is a case that plan->state->crtc exists but plane->fb is NULL, which would be related to vidi driver.
>>>
>>> I just looked into this issue roughly so we would need to check this issue in more details.
>>>
>>> Thanks,
>>> Inki Dae
>>>
>>>> +    DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>>         if (ctx->vblank_on)
>>>>           schedule_work(&ctx->work);
>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
>>>> index 47777be1a754..f40de82848dc 100644
>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
>>>> @@ -37,6 +37,7 @@
>>>>     #include "exynos_drm_drv.h"
>>>>   #include "exynos_drm_crtc.h"
>>>> +#include "exynos_drm_fb.h"
>>>>   #include "exynos_drm_plane.h"
>>>>   #include "exynos_drm_iommu.h"
>>>>   @@ -422,8 +423,8 @@ static void vp_video_buffer(struct mixer_context *ctx,
>>>>           return;
>>>>       }
>>>>   -    luma_addr[0] = plane->dma_addr[0];
>>>> -    chroma_addr[0] = plane->dma_addr[1];
>>>> +    luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
>>>> +    chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
>>>>         if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
>>>>           ctx->interlace = true;
>>>> @@ -575,7 +576,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
>>>>       dst_y_offset = plane->crtc_y;
>>>>         /* converting dma address base and source offset */
>>>> -    dma_addr = plane->dma_addr[0]
>>>> +    dma_addr = exynos_drm_fb_dma_addr(fb, 0)
>>>>           + (plane->src_x * fb->bits_per_pixel >> 3)
>>>>           + (plane->src_y * fb->pitches[0]);
>>>>       src_x_offset = 0;
>>>>
> 
> Best regards
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 06/22] drm/exynos: move dma_addr attribute from exynos plane to exynos fb
  2015-12-11  9:57         ` Inki Dae
@ 2015-12-11 11:27           ` Marek Szyprowski
  2015-12-11 14:52             ` Inki Dae
  0 siblings, 1 reply; 40+ messages in thread
From: Marek Szyprowski @ 2015-12-11 11:27 UTC (permalink / raw)
  To: Inki Dae, dri-devel, linux-samsung-soc
  Cc: Javier Martinez Canillas, Krzysztof Kozlowski, Tobias Jakobi,
	Bartlomiej Zolnierkiewicz, Seung-Woo Kim, Andrzej Hajda

Hi Inki,

On 2015-12-11 10:57, Inki Dae wrote:
> Hi Marek,
>
> 2015년 12월 11일 18:26에 Marek Szyprowski 이(가) 쓴 글:
>> Hi Inki,
>>
>> On 2015-12-11 10:02, Inki Dae wrote:
>>> Hi Marek,
>>>
>>> I found out why NULL point access happened. That was incurred by below your patch,
>>> [PATCH] drm/exynos: move dma_addr attribute from exynos plane to exynos fb
>>>
>>> When another crtc driver is hotplugged in runtime such as HDMI or VIDI,
>>> the drm frambuffer object of fb_helper is set to the plane state of the new crtc driver
>>> so the driver should get the drm framebuffer object from the plane's state or
>>> exynos_plane->pending_fb which is set by exynos_plane_atomic_update function.
>>>
>>> After that, I think the drm framebuffer should be set to drm plane as a current fb
>>> which would be scanned out.
>>>
>>> Anyway, I can fix it like below if you are ok.
>>>
>>> Thanks,
>>> Inki Dae
>>>
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>> @@ -137,7 +137,7 @@ static void vidi_update_plane(struct exynos_drm_crtc *crtc,
>>>           if (ctx->suspended)
>>>                   return;
>>>    -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>> +       addr = exynos_drm_fb_dma_addr(plane->pending_fb, 0);
>>>           DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>
>>> +    plane->base.fb = plane->pending_fb;
>> plane->base.fb should not be modified. I think that the following fix is more
> Could you explain why plane->base.fb shouldn't be modified?

All 'base' classes are modified by DRM core and there should be no need
to modify them from the drivers.

I've checked this issue and the proper fix for is the following code:

--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -131,13 +131,14 @@ static void vidi_disable_vblank(struct 
exynos_drm_crtc *crtc)
  static void vidi_update_plane(struct exynos_drm_crtc *crtc,
                               struct exynos_drm_plane *plane)
  {
+       struct drm_plane_state *state = plane->base.state;
         struct vidi_context *ctx = crtc->ctx;
         dma_addr_t addr;

         if (ctx->suspended)
                 return;

-       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
+       addr = exynos_drm_fb_dma_addr(state->fb, 0);
         DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);

         if (ctx->vblank_on)


plane->base.fb is updated from the core once all crtc/plane atomic update
calls finishes. The drivers should use the fb stored in plane->base.state.
I've missed that VIDI driver doesn't get the fb and incorrectly used
plane->base.fb instad of state->fb while updating the code.


> In case that userspace requests setplane, plane->base.fb would be updated after update_plane callback.
> However, in other cases, I don't see how plane->base.fb could be updated.
> In this case, I think vendor specific drivers would need to update it as a current fb to be scanned out like other some drivers did.
> Of course, it may be possible for drm core part to take care of it appropriately later.
>
> Thanks,
> Inki Dae
>
>> appropriate:
>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>> @@ -132,12 +132,13 @@ static void vidi_update_plane(struct exynos_drm_crtc *crtc,
>>                                struct exynos_drm_plane *plane)
>>   {
>>          struct vidi_context *ctx = crtc->ctx;
>> -       dma_addr_t addr;
>> +       dma_addr_t addr = 0;
>>
>>          if (ctx->suspended)
>>                  return;
>>
>> -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>> +       if (plane->base.fb)
>> +               addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>          DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>
>>          if (ctx->vblank_on)
>>
>> I will investigate the case of NULL plane->state.fb, because it might be relevant
>> to other crtc drivers as well.
>>
>>
>>>             if (ctx->vblank_on)
>>>
>>>
>>> 2015년 12월 10일 22:05에 Inki Dae 이(가) 쓴 글:
>>>> 2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
>>>>> DMA address is a framebuffer attribute and the right place for it is
>>>>> exynos_drm_framebuffer not exynos_drm_plane. This patch also introduces
>>>>> helper function for getting dma address of the given framebuffer.
>>>>>
>>>>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>>>>> Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>>>>> ---
>>>>>    drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 13 ++++++++-----
>>>>>    drivers/gpu/drm/exynos/exynos7_drm_decon.c    | 16 +++++++++-------
>>>>>    drivers/gpu/drm/exynos/exynos_drm_drv.h       |  3 ---
>>>>>    drivers/gpu/drm/exynos/exynos_drm_fb.c        | 16 ++++++----------
>>>>>    drivers/gpu/drm/exynos/exynos_drm_fb.h        |  3 +--
>>>>>    drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 10 ++++++----
>>>>>    drivers/gpu/drm/exynos/exynos_drm_plane.c     | 18 ------------------
>>>>>    drivers/gpu/drm/exynos/exynos_drm_vidi.c      |  5 ++++-
>>>>>    drivers/gpu/drm/exynos/exynos_mixer.c         |  7 ++++---
>>>>>    9 files changed, 38 insertions(+), 53 deletions(-)
>>>>>
>>>> <--snip-->
>>>>
>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>> index 669362c53f49..3ce141236fad 100644
>>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>> @@ -24,6 +24,7 @@
>>>>>      #include "exynos_drm_drv.h"
>>>>>    #include "exynos_drm_crtc.h"
>>>>> +#include "exynos_drm_fb.h"
>>>>>    #include "exynos_drm_plane.h"
>>>>>    #include "exynos_drm_vidi.h"
>>>>>    @@ -126,11 +127,13 @@ static void vidi_update_plane(struct exynos_drm_crtc *crtc,
>>>>>                      struct exynos_drm_plane *plane)
>>>>>    {
>>>>>        struct vidi_context *ctx = crtc->ctx;
>>>>> +    dma_addr_t addr;
>>>>>          if (ctx->suspended)
>>>>>            return;
>>>>>    -    DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
>>>>> +    addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>>> At this point, plane->base.fb is NULL so null pointer access happens like below,
>>>>
>>>> [    5.969422] Unable to handle kernel NULL pointer dereference at virtual address 00000090
>>>> [    5.977481] pgd = ee590000
>>>> [    5.980142] [00000090] *pgd=6e526831, *pte=00000000, *ppte=00000000
>>>> [    5.986347] Internal error: Oops: 17 [#1] PREEMPT SMP ARM
>>>> [    5.991712] Modules linked in:
>>>> [    5.994770] CPU: 3 PID: 1598 Comm: sh Not tainted 4.4.0-rc3-00052-gc60d7e2-dirty #199
>>>> [    6.002565] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
>>>> [    6.008647] task: ef328000 ti: ee4d4000 task.ti: ee4d4000
>>>> [    6.014053] PC is at exynos_drm_fb_dma_addr+0x8/0x14
>>>> [    6.018990] LR is at vidi_update_plane+0x4c/0xc4
>>>> [    6.023581] pc : [<c02b1fb4>]    lr : [<c02c3cc4>]    psr: 80000013
>>>> [    6.023581] sp : ee4d5d90  ip : 00000001  fp : 00000000
>>>> [    6.035029] r10: 00000000  r9 : c05b965c  r8 : ee813e00
>>>> [    6.040241] r7 : 00000000  r6 : ee8e3330  r5 : 00000000  r4 : ee8e3010
>>>> [    6.046749] r3 : 00000000  r2 : 00000000  r1 : 00000024  r0 : 00000000
>>>> [    6.053264] Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
>>>> [    6.060379] Control: 10c5387d  Table: 6e59004a  DAC: 00000051
>>>> [    6.066107] Process sh (pid: 1598, stack limit = 0xee4d4210)
>>>> [    6.071748] Stack: (0xee4d5d90 to 0xee4d6000)
>>>> [    6.076100] 5d80:                                     00000000 ee813300 ee476e40 00000005
>>>> [    6.084236] 5da0: ee8e3330 c028ac14 00000008 ee476e40 ee476fc0 ef3b3800 ee476fc0 eeb3e380
>>>> [    6.092395] 5dc0: 00000002 c02b08e4 00000000 eeb3e3a4 ee476fc0 ee476e40 ef3b3800 eeb3e380
>>>> [    6.100554] 5de0: 00000002 c02b12b8 ee854400 00000000 00000001 ee8501a8 00000000 ee476e40
>>>> [    6.108714] 5e00: ef3b3800 00000001 ee476e40 00000050 ee850c80 00000001 ee476e40 ef3b3aac
>>>> [    6.116873] 5e20: 00000002 000000ff 00000000 c028e0ec 000a82b4 c02acc50 ee8e36a0 ee476c80
>>>> [    6.125032] 5e40: ef3b3aac ef3b3800 ee476c9c ee850c80 ef3b3800 ef3b3800 ef3b3800 ef3b398c
>>>> [    6.133191] 5e60: c088c390 00000002 000a82b4 c028f8d4 00000000 ef3b3800 ef0f4300 c028f948
>>>> [    6.141350] 5e80: ee850c80 c028f864 ef3b3a84 00000001 ef3b3a90 c02853e4 00000001 00000000
>>>> [    6.149509] 5ea0: 000a82b4 ee4d5ec0 00000002 ee8e3010 00000002 00000002 ee4d5f88 00000000
>>>> [    6.157669] 5ec0: 00000000 eeb8df00 000a82b4 c02c4278 00000002 ee476b00 eeb8df0c c01390ac
>>>> [    6.165828] 5ee0: 00000000 00000000 ee4e1f00 00000002 000a9540 ee4d5f88 c000f844 ee4d4000
>>>> [    6.173987] 5f00: 00000000 c00dbf70 000a82b4 c00093dc ee4d4000 ee4d5f78 ef328234 c0579bec
>>>> [    6.182146] 5f20: 00000001 00000001 ee4d5f3c 00000001 ee45e9c4 00000001 000a82b4 c005ca74
>>>> [    6.190306] 5f40: ee45e9c4 00000002 000a9540 c005cad4 ee4e1f00 00000002 000a9540 ee4d5f88
>>>> [    6.198465] 5f60: c000f844 c00dc770 00000000 00000000 ee4e1f00 ee4e1f00 00000002 000a9540
>>>> [    6.206624] 5f80: c000f844 c00dcf98 00000000 00000000 00000003 000a7c40 00000001 000a9540
>>>> [    6.214783] 5fa0: 00000004 c000f680 000a7c40 00000001 00000001 000a9540 00000002 00000000
>>>> [    6.222942] 5fc0: 000a7c40 00000001 000a9540 00000004 00000020 000a82c8 000a8294 000a82b4
>>>> [    6.231102] 5fe0: 00000000 be8b1624 00012345 b6e94166 40000030 00000001 00000000 00000000
>>>> [    6.239270] [<c02b1fb4>] (exynos_drm_fb_dma_addr) from [<c02c3cc4>] (vidi_update_plane+0x4c/0xc4)
>>>> [    6.248122] [<c02c3cc4>] (vidi_update_plane) from [<c028ac14>] (drm_atomic_helper_commit_planes+0x1f4/0x258)
>>>> [    6.257928] [<c028ac14>] (drm_atomic_helper_commit_planes) from [<c02b08e4>] (exynos_atomic_commit_complete+0xe4/0x1c4)
>>>> [    6.268688] [<c02b08e4>] (exynos_atomic_commit_complete) from [<c02b12b8>] (exynos_atomic_commit+0x180/0x1cc)
>>>> [    6.278584] [<c02b12b8>] (exynos_atomic_commit) from [<c028e0ec>] (restore_fbdev_mode+0x260/0x290)
>>>> [    6.287525] [<c028e0ec>] (restore_fbdev_mode) from [<c028f8d4>] (drm_fb_helper_restore_fbdev_mode_unlocked+0x30/0x74)
>>>> [    6.298111] [<c028f8d4>] (drm_fb_helper_restore_fbdev_mode_unlocked) from [<c028f948>] (drm_fb_helper_set_par+0x30/0x54)
>>>> [    6.308961] [<c028f948>] (drm_fb_helper_set_par) from [<c028f864>] (drm_fb_helper_hotplug_event+0x9c/0xdc)
>>>> [    6.318595] [<c028f864>] (drm_fb_helper_hotplug_event) from [<c02853e4>] (drm_helper_hpd_irq_event+0xd4/0x160)
>>>> [    6.328578] [<c02853e4>] (drm_helper_hpd_irq_event) from [<c02c4278>] (vidi_store_connection+0x94/0xcc)
>>>> [    6.337954] [<c02c4278>] (vidi_store_connection) from [<c01390ac>] (kernfs_fop_write+0xb8/0x1bc)
>>>> [    6.346723] [<c01390ac>] (kernfs_fop_write) from [<c00dbf70>] (__vfs_write+0x20/0xd8)
>>>> [    6.354531] [<c00dbf70>] (__vfs_write) from [<c00dc770>] (vfs_write+0x90/0x164)
>>>> [    6.361821] [<c00dc770>] (vfs_write) from [<c00dcf98>] (SyS_write+0x44/0x9c)
>>>> [    6.368855] [<c00dcf98>] (SyS_write) from [<c000f680>] (ret_fast_syscall+0x0/0x3c)
>>>> [    6.376404] Code: eb0b17f1 eaffffe7 e3510003 d2811024 (d7900101)
>>>>
>>>> When vidi driver is intiated by triggering a connection sysfs file, vidi driver tries modeset binding by calling drm_fb_helper_hotplug_event.
>>>> However, at this time it seems there is a case that plan->state->crtc exists but plane->fb is NULL, which would be related to vidi driver.
>>>>
>>>> I just looked into this issue roughly so we would need to check this issue in more details.
>>>>
>>>> Thanks,
>>>> Inki Dae
>>>>
>>>>> +    DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>>>          if (ctx->vblank_on)
>>>>>            schedule_work(&ctx->work);
>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>> index 47777be1a754..f40de82848dc 100644
>>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>> @@ -37,6 +37,7 @@
>>>>>      #include "exynos_drm_drv.h"
>>>>>    #include "exynos_drm_crtc.h"
>>>>> +#include "exynos_drm_fb.h"
>>>>>    #include "exynos_drm_plane.h"
>>>>>    #include "exynos_drm_iommu.h"
>>>>>    @@ -422,8 +423,8 @@ static void vp_video_buffer(struct mixer_context *ctx,
>>>>>            return;
>>>>>        }
>>>>>    -    luma_addr[0] = plane->dma_addr[0];
>>>>> -    chroma_addr[0] = plane->dma_addr[1];
>>>>> +    luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
>>>>> +    chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
>>>>>          if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
>>>>>            ctx->interlace = true;
>>>>> @@ -575,7 +576,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
>>>>>        dst_y_offset = plane->crtc_y;
>>>>>          /* converting dma address base and source offset */
>>>>> -    dma_addr = plane->dma_addr[0]
>>>>> +    dma_addr = exynos_drm_fb_dma_addr(fb, 0)
>>>>>            + (plane->src_x * fb->bits_per_pixel >> 3)
>>>>>            + (plane->src_y * fb->pitches[0]);
>>>>>        src_x_offset = 0;
>>>>>
>>>>>
>>>>>

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

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

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

* Re: [PATCH v2 06/22] drm/exynos: move dma_addr attribute from exynos plane to exynos fb
  2015-12-11 11:27           ` Marek Szyprowski
@ 2015-12-11 14:52             ` Inki Dae
  2015-12-14  9:15               ` Marek Szyprowski
  0 siblings, 1 reply; 40+ messages in thread
From: Inki Dae @ 2015-12-11 14:52 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Krzysztof Kozlowski, linux-samsung-soc,
	Bartlomiej Zolnierkiewicz, Seung-Woo Kim, DRI mailing list,
	Andrzej Hajda, Javier Martinez Canillas, Tobias Jakobi

Hi Marek,

2015-12-11 20:27 GMT+09:00 Marek Szyprowski <m.szyprowski@samsung.com>:
> Hi Inki,
>
>
> On 2015-12-11 10:57, Inki Dae wrote:
>>
>> Hi Marek,
>>
>> 2015년 12월 11일 18:26에 Marek Szyprowski 이(가) 쓴 글:
>>>
>>> Hi Inki,
>>>
>>> On 2015-12-11 10:02, Inki Dae wrote:
>>>>
>>>> Hi Marek,
>>>>
>>>> I found out why NULL point access happened. That was incurred by below
>>>> your patch,
>>>> [PATCH] drm/exynos: move dma_addr attribute from exynos plane to exynos
>>>> fb
>>>>
>>>> When another crtc driver is hotplugged in runtime such as HDMI or VIDI,
>>>> the drm frambuffer object of fb_helper is set to the plane state of the
>>>> new crtc driver
>>>> so the driver should get the drm framebuffer object from the plane's
>>>> state or
>>>> exynos_plane->pending_fb which is set by exynos_plane_atomic_update
>>>> function.
>>>>
>>>> After that, I think the drm framebuffer should be set to drm plane as a
>>>> current fb
>>>> which would be scanned out.
>>>>
>>>> Anyway, I can fix it like below if you are ok.
>>>>
>>>> Thanks,
>>>> Inki Dae
>>>>
>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>> @@ -137,7 +137,7 @@ static void vidi_update_plane(struct exynos_drm_crtc
>>>> *crtc,
>>>>           if (ctx->suspended)
>>>>                   return;
>>>>    -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>>> +       addr = exynos_drm_fb_dma_addr(plane->pending_fb, 0);
>>>>           DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>>
>>>> +    plane->base.fb = plane->pending_fb;
>>>
>>> plane->base.fb should not be modified. I think that the following fix is
>>> more
>>
>> Could you explain why plane->base.fb shouldn't be modified?
>
>
> All 'base' classes are modified by DRM core and there should be no need
> to modify them from the drivers.

Ok, If so - drm core updates plane->fb - then it's reasonable. But I
couldn't find the exact location where plane->fb is set to a fb to be
scanned out.
So could you let me know the exact location? it's not clear to me yet.

>
> I've checked this issue and the proper fix for is the following code:
>
> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> @@ -131,13 +131,14 @@ static void vidi_disable_vblank(struct exynos_drm_crtc
> *crtc)
>  static void vidi_update_plane(struct exynos_drm_crtc *crtc,
>                               struct exynos_drm_plane *plane)
>  {
> +       struct drm_plane_state *state = plane->base.state;
>         struct vidi_context *ctx = crtc->ctx;
>         dma_addr_t addr;
>
>         if (ctx->suspended)
>                 return;
>
> -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
> +       addr = exynos_drm_fb_dma_addr(state->fb, 0);
>         DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>
>         if (ctx->vblank_on)
>
>
> plane->base.fb is updated from the core once all crtc/plane atomic update
> calls finishes. The drivers should use the fb stored in plane->base.state.
> I've missed that VIDI driver doesn't get the fb and incorrectly used
> plane->base.fb instad of state->fb while updating the code.
>

Actually, I used state->fb instead of plane->pending_fb but in
exynos_plane_atomic_update function, plane->pending_fb is set to
state->fb.
That is why I commented like below,
" so the driver should get the drm framebuffer object from the plane's
state or exynos_plane->pending_fb which is set by
exynos_plane_atomic_update function."

Anyway, using state->fb looks like more consistent with other drivers,
fimd, decon and mixer.

Thanks,
Inki Dae

>
>
>> In case that userspace requests setplane, plane->base.fb would be updated
>> after update_plane callback.
>> However, in other cases, I don't see how plane->base.fb could be updated.
>> In this case, I think vendor specific drivers would need to update it as a
>> current fb to be scanned out like other some drivers did.
>> Of course, it may be possible for drm core part to take care of it
>> appropriately later.
>>
>> Thanks,
>> Inki Dae
>>
>>> appropriate:
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>> @@ -132,12 +132,13 @@ static void vidi_update_plane(struct
>>> exynos_drm_crtc *crtc,
>>>                                struct exynos_drm_plane *plane)
>>>   {
>>>          struct vidi_context *ctx = crtc->ctx;
>>> -       dma_addr_t addr;
>>> +       dma_addr_t addr = 0;
>>>
>>>          if (ctx->suspended)
>>>                  return;
>>>
>>> -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>> +       if (plane->base.fb)
>>> +               addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>>          DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>
>>>          if (ctx->vblank_on)
>>>
>>> I will investigate the case of NULL plane->state.fb, because it might be
>>> relevant
>>> to other crtc drivers as well.
>>>
>>>
>>>>             if (ctx->vblank_on)
>>>>
>>>>
>>>> 2015년 12월 10일 22:05에 Inki Dae 이(가) 쓴 글:
>>>>>
>>>>> 2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
>>>>>>
>>>>>> DMA address is a framebuffer attribute and the right place for it is
>>>>>> exynos_drm_framebuffer not exynos_drm_plane. This patch also
>>>>>> introduces
>>>>>> helper function for getting dma address of the given framebuffer.
>>>>>>
>>>>>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>>>>>> Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>>>>>> ---
>>>>>>    drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 13 ++++++++-----
>>>>>>    drivers/gpu/drm/exynos/exynos7_drm_decon.c    | 16 +++++++++-------
>>>>>>    drivers/gpu/drm/exynos/exynos_drm_drv.h       |  3 ---
>>>>>>    drivers/gpu/drm/exynos/exynos_drm_fb.c        | 16 ++++++----------
>>>>>>    drivers/gpu/drm/exynos/exynos_drm_fb.h        |  3 +--
>>>>>>    drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 10 ++++++----
>>>>>>    drivers/gpu/drm/exynos/exynos_drm_plane.c     | 18
>>>>>> ------------------
>>>>>>    drivers/gpu/drm/exynos/exynos_drm_vidi.c      |  5 ++++-
>>>>>>    drivers/gpu/drm/exynos/exynos_mixer.c         |  7 ++++---
>>>>>>    9 files changed, 38 insertions(+), 53 deletions(-)
>>>>>>
>>>>> <--snip-->
>>>>>
>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>> b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>> index 669362c53f49..3ce141236fad 100644
>>>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>> @@ -24,6 +24,7 @@
>>>>>>      #include "exynos_drm_drv.h"
>>>>>>    #include "exynos_drm_crtc.h"
>>>>>> +#include "exynos_drm_fb.h"
>>>>>>    #include "exynos_drm_plane.h"
>>>>>>    #include "exynos_drm_vidi.h"
>>>>>>    @@ -126,11 +127,13 @@ static void vidi_update_plane(struct
>>>>>> exynos_drm_crtc *crtc,
>>>>>>                      struct exynos_drm_plane *plane)
>>>>>>    {
>>>>>>        struct vidi_context *ctx = crtc->ctx;
>>>>>> +    dma_addr_t addr;
>>>>>>          if (ctx->suspended)
>>>>>>            return;
>>>>>>    -    DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
>>>>>> +    addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>>>>
>>>>> At this point, plane->base.fb is NULL so null pointer access happens
>>>>> like below,
>>>>>
>>>>> [    5.969422] Unable to handle kernel NULL pointer dereference at
>>>>> virtual address 00000090
>>>>> [    5.977481] pgd = ee590000
>>>>> [    5.980142] [00000090] *pgd=6e526831, *pte=00000000, *ppte=00000000
>>>>> [    5.986347] Internal error: Oops: 17 [#1] PREEMPT SMP ARM
>>>>> [    5.991712] Modules linked in:
>>>>> [    5.994770] CPU: 3 PID: 1598 Comm: sh Not tainted
>>>>> 4.4.0-rc3-00052-gc60d7e2-dirty #199
>>>>> [    6.002565] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
>>>>> [    6.008647] task: ef328000 ti: ee4d4000 task.ti: ee4d4000
>>>>> [    6.014053] PC is at exynos_drm_fb_dma_addr+0x8/0x14
>>>>> [    6.018990] LR is at vidi_update_plane+0x4c/0xc4
>>>>> [    6.023581] pc : [<c02b1fb4>]    lr : [<c02c3cc4>]    psr: 80000013
>>>>> [    6.023581] sp : ee4d5d90  ip : 00000001  fp : 00000000
>>>>> [    6.035029] r10: 00000000  r9 : c05b965c  r8 : ee813e00
>>>>> [    6.040241] r7 : 00000000  r6 : ee8e3330  r5 : 00000000  r4 :
>>>>> ee8e3010
>>>>> [    6.046749] r3 : 00000000  r2 : 00000000  r1 : 00000024  r0 :
>>>>> 00000000
>>>>> [    6.053264] Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM
>>>>> Segment none
>>>>> [    6.060379] Control: 10c5387d  Table: 6e59004a  DAC: 00000051
>>>>> [    6.066107] Process sh (pid: 1598, stack limit = 0xee4d4210)
>>>>> [    6.071748] Stack: (0xee4d5d90 to 0xee4d6000)
>>>>> [    6.076100] 5d80:                                     00000000
>>>>> ee813300 ee476e40 00000005
>>>>> [    6.084236] 5da0: ee8e3330 c028ac14 00000008 ee476e40 ee476fc0
>>>>> ef3b3800 ee476fc0 eeb3e380
>>>>> [    6.092395] 5dc0: 00000002 c02b08e4 00000000 eeb3e3a4 ee476fc0
>>>>> ee476e40 ef3b3800 eeb3e380
>>>>> [    6.100554] 5de0: 00000002 c02b12b8 ee854400 00000000 00000001
>>>>> ee8501a8 00000000 ee476e40
>>>>> [    6.108714] 5e00: ef3b3800 00000001 ee476e40 00000050 ee850c80
>>>>> 00000001 ee476e40 ef3b3aac
>>>>> [    6.116873] 5e20: 00000002 000000ff 00000000 c028e0ec 000a82b4
>>>>> c02acc50 ee8e36a0 ee476c80
>>>>> [    6.125032] 5e40: ef3b3aac ef3b3800 ee476c9c ee850c80 ef3b3800
>>>>> ef3b3800 ef3b3800 ef3b398c
>>>>> [    6.133191] 5e60: c088c390 00000002 000a82b4 c028f8d4 00000000
>>>>> ef3b3800 ef0f4300 c028f948
>>>>> [    6.141350] 5e80: ee850c80 c028f864 ef3b3a84 00000001 ef3b3a90
>>>>> c02853e4 00000001 00000000
>>>>> [    6.149509] 5ea0: 000a82b4 ee4d5ec0 00000002 ee8e3010 00000002
>>>>> 00000002 ee4d5f88 00000000
>>>>> [    6.157669] 5ec0: 00000000 eeb8df00 000a82b4 c02c4278 00000002
>>>>> ee476b00 eeb8df0c c01390ac
>>>>> [    6.165828] 5ee0: 00000000 00000000 ee4e1f00 00000002 000a9540
>>>>> ee4d5f88 c000f844 ee4d4000
>>>>> [    6.173987] 5f00: 00000000 c00dbf70 000a82b4 c00093dc ee4d4000
>>>>> ee4d5f78 ef328234 c0579bec
>>>>> [    6.182146] 5f20: 00000001 00000001 ee4d5f3c 00000001 ee45e9c4
>>>>> 00000001 000a82b4 c005ca74
>>>>> [    6.190306] 5f40: ee45e9c4 00000002 000a9540 c005cad4 ee4e1f00
>>>>> 00000002 000a9540 ee4d5f88
>>>>> [    6.198465] 5f60: c000f844 c00dc770 00000000 00000000 ee4e1f00
>>>>> ee4e1f00 00000002 000a9540
>>>>> [    6.206624] 5f80: c000f844 c00dcf98 00000000 00000000 00000003
>>>>> 000a7c40 00000001 000a9540
>>>>> [    6.214783] 5fa0: 00000004 c000f680 000a7c40 00000001 00000001
>>>>> 000a9540 00000002 00000000
>>>>> [    6.222942] 5fc0: 000a7c40 00000001 000a9540 00000004 00000020
>>>>> 000a82c8 000a8294 000a82b4
>>>>> [    6.231102] 5fe0: 00000000 be8b1624 00012345 b6e94166 40000030
>>>>> 00000001 00000000 00000000
>>>>> [    6.239270] [<c02b1fb4>] (exynos_drm_fb_dma_addr) from [<c02c3cc4>]
>>>>> (vidi_update_plane+0x4c/0xc4)
>>>>> [    6.248122] [<c02c3cc4>] (vidi_update_plane) from [<c028ac14>]
>>>>> (drm_atomic_helper_commit_planes+0x1f4/0x258)
>>>>> [    6.257928] [<c028ac14>] (drm_atomic_helper_commit_planes) from
>>>>> [<c02b08e4>] (exynos_atomic_commit_complete+0xe4/0x1c4)
>>>>> [    6.268688] [<c02b08e4>] (exynos_atomic_commit_complete) from
>>>>> [<c02b12b8>] (exynos_atomic_commit+0x180/0x1cc)
>>>>> [    6.278584] [<c02b12b8>] (exynos_atomic_commit) from [<c028e0ec>]
>>>>> (restore_fbdev_mode+0x260/0x290)
>>>>> [    6.287525] [<c028e0ec>] (restore_fbdev_mode) from [<c028f8d4>]
>>>>> (drm_fb_helper_restore_fbdev_mode_unlocked+0x30/0x74)
>>>>> [    6.298111] [<c028f8d4>] (drm_fb_helper_restore_fbdev_mode_unlocked)
>>>>> from [<c028f948>] (drm_fb_helper_set_par+0x30/0x54)
>>>>> [    6.308961] [<c028f948>] (drm_fb_helper_set_par) from [<c028f864>]
>>>>> (drm_fb_helper_hotplug_event+0x9c/0xdc)
>>>>> [    6.318595] [<c028f864>] (drm_fb_helper_hotplug_event) from
>>>>> [<c02853e4>] (drm_helper_hpd_irq_event+0xd4/0x160)
>>>>> [    6.328578] [<c02853e4>] (drm_helper_hpd_irq_event) from
>>>>> [<c02c4278>] (vidi_store_connection+0x94/0xcc)
>>>>> [    6.337954] [<c02c4278>] (vidi_store_connection) from [<c01390ac>]
>>>>> (kernfs_fop_write+0xb8/0x1bc)
>>>>> [    6.346723] [<c01390ac>] (kernfs_fop_write) from [<c00dbf70>]
>>>>> (__vfs_write+0x20/0xd8)
>>>>> [    6.354531] [<c00dbf70>] (__vfs_write) from [<c00dc770>]
>>>>> (vfs_write+0x90/0x164)
>>>>> [    6.361821] [<c00dc770>] (vfs_write) from [<c00dcf98>]
>>>>> (SyS_write+0x44/0x9c)
>>>>> [    6.368855] [<c00dcf98>] (SyS_write) from [<c000f680>]
>>>>> (ret_fast_syscall+0x0/0x3c)
>>>>> [    6.376404] Code: eb0b17f1 eaffffe7 e3510003 d2811024 (d7900101)
>>>>>
>>>>> When vidi driver is intiated by triggering a connection sysfs file,
>>>>> vidi driver tries modeset binding by calling drm_fb_helper_hotplug_event.
>>>>> However, at this time it seems there is a case that plan->state->crtc
>>>>> exists but plane->fb is NULL, which would be related to vidi driver.
>>>>>
>>>>> I just looked into this issue roughly so we would need to check this
>>>>> issue in more details.
>>>>>
>>>>> Thanks,
>>>>> Inki Dae
>>>>>
>>>>>> +    DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>>>>          if (ctx->vblank_on)
>>>>>>            schedule_work(&ctx->work);
>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>>> b/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>>> index 47777be1a754..f40de82848dc 100644
>>>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>>> @@ -37,6 +37,7 @@
>>>>>>      #include "exynos_drm_drv.h"
>>>>>>    #include "exynos_drm_crtc.h"
>>>>>> +#include "exynos_drm_fb.h"
>>>>>>    #include "exynos_drm_plane.h"
>>>>>>    #include "exynos_drm_iommu.h"
>>>>>>    @@ -422,8 +423,8 @@ static void vp_video_buffer(struct
>>>>>> mixer_context *ctx,
>>>>>>            return;
>>>>>>        }
>>>>>>    -    luma_addr[0] = plane->dma_addr[0];
>>>>>> -    chroma_addr[0] = plane->dma_addr[1];
>>>>>> +    luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
>>>>>> +    chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
>>>>>>          if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
>>>>>>            ctx->interlace = true;
>>>>>> @@ -575,7 +576,7 @@ static void mixer_graph_buffer(struct
>>>>>> mixer_context *ctx,
>>>>>>        dst_y_offset = plane->crtc_y;
>>>>>>          /* converting dma address base and source offset */
>>>>>> -    dma_addr = plane->dma_addr[0]
>>>>>> +    dma_addr = exynos_drm_fb_dma_addr(fb, 0)
>>>>>>            + (plane->src_x * fb->bits_per_pixel >> 3)
>>>>>>            + (plane->src_y * fb->pitches[0]);
>>>>>>        src_x_offset = 0;
>>>>>>
>>>>>>
>>>>>>
>
> Best regards
> --
> Marek Szyprowski, PhD
> Samsung R&D Institute Poland
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 06/22] drm/exynos: move dma_addr attribute from exynos plane to exynos fb
  2015-12-11 14:52             ` Inki Dae
@ 2015-12-14  9:15               ` Marek Szyprowski
  2015-12-14  9:43                 ` Inki Dae
  0 siblings, 1 reply; 40+ messages in thread
From: Marek Szyprowski @ 2015-12-14  9:15 UTC (permalink / raw)
  To: Inki Dae
  Cc: Krzysztof Kozlowski, linux-samsung-soc,
	Bartlomiej Zolnierkiewicz, Seung-Woo Kim, DRI mailing list,
	Andrzej Hajda, Javier Martinez Canillas, Tobias Jakobi

Hi Inki,

On 2015-12-11 15:52, Inki Dae wrote:
> 2015-12-11 20:27 GMT+09:00 Marek Szyprowski <m.szyprowski@samsung.com>:
>> On 2015-12-11 10:57, Inki Dae wrote:
>>> 2015년 12월 11일 18:26에 Marek Szyprowski 이(가) 쓴 글:
>>>> On 2015-12-11 10:02, Inki Dae wrote:
>>>>> I found out why NULL point access happened. That was incurred by below
>>>>> your patch,
>>>>> [PATCH] drm/exynos: move dma_addr attribute from exynos plane to exynos
>>>>> fb
>>>>>
>>>>> When another crtc driver is hotplugged in runtime such as HDMI or VIDI,
>>>>> the drm frambuffer object of fb_helper is set to the plane state of the
>>>>> new crtc driver
>>>>> so the driver should get the drm framebuffer object from the plane's
>>>>> state or
>>>>> exynos_plane->pending_fb which is set by exynos_plane_atomic_update
>>>>> function.
>>>>>
>>>>> After that, I think the drm framebuffer should be set to drm plane as a
>>>>> current fb
>>>>> which would be scanned out.
>>>>>
>>>>> Anyway, I can fix it like below if you are ok.
>>>>>
>>>>> Thanks,
>>>>> Inki Dae
>>>>>
>>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>> @@ -137,7 +137,7 @@ static void vidi_update_plane(struct exynos_drm_crtc
>>>>> *crtc,
>>>>>            if (ctx->suspended)
>>>>>                    return;
>>>>>     -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>>>> +       addr = exynos_drm_fb_dma_addr(plane->pending_fb, 0);
>>>>>            DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>>>
>>>>> +    plane->base.fb = plane->pending_fb;
>>>> plane->base.fb should not be modified. I think that the following fix is
>>>> more
>>> Could you explain why plane->base.fb shouldn't be modified?
>>
>> All 'base' classes are modified by DRM core and there should be no need
>> to modify them from the drivers.
> Ok, If so - drm core updates plane->fb - then it's reasonable. But I
> couldn't find the exact location where plane->fb is set to a fb to be
> scanned out.
> So could you let me know the exact location? it's not clear to me yet.

Setting plane->fb is wired somewhere in the atomic update logic, see
__setplane_internal() function in drivers/gpu/drm/drm_crtc.c. Some more 
comments
are also in the drm_atomic_clean_old_fb() function in 
drivers/gpu/drm/drm_atomic.c
However I don't know the exact call path.

>> I've checked this issue and the proper fix for is the following code:
>>
>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>> @@ -131,13 +131,14 @@ static void vidi_disable_vblank(struct exynos_drm_crtc
>> *crtc)
>>   static void vidi_update_plane(struct exynos_drm_crtc *crtc,
>>                                struct exynos_drm_plane *plane)
>>   {
>> +       struct drm_plane_state *state = plane->base.state;
>>          struct vidi_context *ctx = crtc->ctx;
>>          dma_addr_t addr;
>>
>>          if (ctx->suspended)
>>                  return;
>>
>> -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>> +       addr = exynos_drm_fb_dma_addr(state->fb, 0);
>>          DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>
>>          if (ctx->vblank_on)
>>
>>
>> plane->base.fb is updated from the core once all crtc/plane atomic update
>> calls finishes. The drivers should use the fb stored in plane->base.state.
>> I've missed that VIDI driver doesn't get the fb and incorrectly used
>> plane->base.fb instad of state->fb while updating the code.
>>
> Actually, I used state->fb instead of plane->pending_fb but in
> exynos_plane_atomic_update function, plane->pending_fb is set to
> state->fb.
> That is why I commented like below,
> " so the driver should get the drm framebuffer object from the plane's
> state or exynos_plane->pending_fb which is set by
> exynos_plane_atomic_update function."
>
> Anyway, using state->fb looks like more consistent with other drivers,
> fimd, decon and mixer.

Thanks for applying my fix and merging this patch.

>>> In case that userspace requests setplane, plane->base.fb would be updated
>>> after update_plane callback.
>>> However, in other cases, I don't see how plane->base.fb could be updated.
>>> In this case, I think vendor specific drivers would need to update it as a
>>> current fb to be scanned out like other some drivers did.
>>> Of course, it may be possible for drm core part to take care of it
>>> appropriately later.
>>>
>>> Thanks,
>>> Inki Dae
>>>
>>>> appropriate:
>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>> @@ -132,12 +132,13 @@ static void vidi_update_plane(struct
>>>> exynos_drm_crtc *crtc,
>>>>                                 struct exynos_drm_plane *plane)
>>>>    {
>>>>           struct vidi_context *ctx = crtc->ctx;
>>>> -       dma_addr_t addr;
>>>> +       dma_addr_t addr = 0;
>>>>
>>>>           if (ctx->suspended)
>>>>                   return;
>>>>
>>>> -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>>> +       if (plane->base.fb)
>>>> +               addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>>>           DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>>
>>>>           if (ctx->vblank_on)
>>>>
>>>> I will investigate the case of NULL plane->state.fb, because it might be
>>>> relevant
>>>> to other crtc drivers as well.
>>>>
>>>>
>>>>>              if (ctx->vblank_on)
>>>>>
>>>>>
>>>>> 2015년 12월 10일 22:05에 Inki Dae 이(가) 쓴 글:
>>>>>> 2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
>>>>>>> DMA address is a framebuffer attribute and the right place for it is
>>>>>>> exynos_drm_framebuffer not exynos_drm_plane. This patch also
>>>>>>> introduces
>>>>>>> helper function for getting dma address of the given framebuffer.
>>>>>>>
>>>>>>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>>>>>>> Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>>>>>>> ---
>>>>>>>     drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 13 ++++++++-----
>>>>>>>     drivers/gpu/drm/exynos/exynos7_drm_decon.c    | 16 +++++++++-------
>>>>>>>     drivers/gpu/drm/exynos/exynos_drm_drv.h       |  3 ---
>>>>>>>     drivers/gpu/drm/exynos/exynos_drm_fb.c        | 16 ++++++----------
>>>>>>>     drivers/gpu/drm/exynos/exynos_drm_fb.h        |  3 +--
>>>>>>>     drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 10 ++++++----
>>>>>>>     drivers/gpu/drm/exynos/exynos_drm_plane.c     | 18
>>>>>>> ------------------
>>>>>>>     drivers/gpu/drm/exynos/exynos_drm_vidi.c      |  5 ++++-
>>>>>>>     drivers/gpu/drm/exynos/exynos_mixer.c         |  7 ++++---
>>>>>>>     9 files changed, 38 insertions(+), 53 deletions(-)
>>>>>>>
>>>>>> <--snip-->
>>>>>>
>>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>>> b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>>> index 669362c53f49..3ce141236fad 100644
>>>>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>>> @@ -24,6 +24,7 @@
>>>>>>>       #include "exynos_drm_drv.h"
>>>>>>>     #include "exynos_drm_crtc.h"
>>>>>>> +#include "exynos_drm_fb.h"
>>>>>>>     #include "exynos_drm_plane.h"
>>>>>>>     #include "exynos_drm_vidi.h"
>>>>>>>     @@ -126,11 +127,13 @@ static void vidi_update_plane(struct
>>>>>>> exynos_drm_crtc *crtc,
>>>>>>>                       struct exynos_drm_plane *plane)
>>>>>>>     {
>>>>>>>         struct vidi_context *ctx = crtc->ctx;
>>>>>>> +    dma_addr_t addr;
>>>>>>>           if (ctx->suspended)
>>>>>>>             return;
>>>>>>>     -    DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
>>>>>>> +    addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>>>>> At this point, plane->base.fb is NULL so null pointer access happens
>>>>>> like below,
>>>>>>
>>>>>> [    5.969422] Unable to handle kernel NULL pointer dereference at
>>>>>> virtual address 00000090
>>>>>> [    5.977481] pgd = ee590000
>>>>>> [    5.980142] [00000090] *pgd=6e526831, *pte=00000000, *ppte=00000000
>>>>>> [    5.986347] Internal error: Oops: 17 [#1] PREEMPT SMP ARM
>>>>>> [    5.991712] Modules linked in:
>>>>>> [    5.994770] CPU: 3 PID: 1598 Comm: sh Not tainted
>>>>>> 4.4.0-rc3-00052-gc60d7e2-dirty #199
>>>>>> [    6.002565] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
>>>>>> [    6.008647] task: ef328000 ti: ee4d4000 task.ti: ee4d4000
>>>>>> [    6.014053] PC is at exynos_drm_fb_dma_addr+0x8/0x14
>>>>>> [    6.018990] LR is at vidi_update_plane+0x4c/0xc4
>>>>>> [    6.023581] pc : [<c02b1fb4>]    lr : [<c02c3cc4>]    psr: 80000013
>>>>>> [    6.023581] sp : ee4d5d90  ip : 00000001  fp : 00000000
>>>>>> [    6.035029] r10: 00000000  r9 : c05b965c  r8 : ee813e00
>>>>>> [    6.040241] r7 : 00000000  r6 : ee8e3330  r5 : 00000000  r4 :
>>>>>> ee8e3010
>>>>>> [    6.046749] r3 : 00000000  r2 : 00000000  r1 : 00000024  r0 :
>>>>>> 00000000
>>>>>> [    6.053264] Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM
>>>>>> Segment none
>>>>>> [    6.060379] Control: 10c5387d  Table: 6e59004a  DAC: 00000051
>>>>>> [    6.066107] Process sh (pid: 1598, stack limit = 0xee4d4210)
>>>>>> [    6.071748] Stack: (0xee4d5d90 to 0xee4d6000)
>>>>>> [    6.076100] 5d80:                                     00000000
>>>>>> ee813300 ee476e40 00000005
>>>>>> [    6.084236] 5da0: ee8e3330 c028ac14 00000008 ee476e40 ee476fc0
>>>>>> ef3b3800 ee476fc0 eeb3e380
>>>>>> [    6.092395] 5dc0: 00000002 c02b08e4 00000000 eeb3e3a4 ee476fc0
>>>>>> ee476e40 ef3b3800 eeb3e380
>>>>>> [    6.100554] 5de0: 00000002 c02b12b8 ee854400 00000000 00000001
>>>>>> ee8501a8 00000000 ee476e40
>>>>>> [    6.108714] 5e00: ef3b3800 00000001 ee476e40 00000050 ee850c80
>>>>>> 00000001 ee476e40 ef3b3aac
>>>>>> [    6.116873] 5e20: 00000002 000000ff 00000000 c028e0ec 000a82b4
>>>>>> c02acc50 ee8e36a0 ee476c80
>>>>>> [    6.125032] 5e40: ef3b3aac ef3b3800 ee476c9c ee850c80 ef3b3800
>>>>>> ef3b3800 ef3b3800 ef3b398c
>>>>>> [    6.133191] 5e60: c088c390 00000002 000a82b4 c028f8d4 00000000
>>>>>> ef3b3800 ef0f4300 c028f948
>>>>>> [    6.141350] 5e80: ee850c80 c028f864 ef3b3a84 00000001 ef3b3a90
>>>>>> c02853e4 00000001 00000000
>>>>>> [    6.149509] 5ea0: 000a82b4 ee4d5ec0 00000002 ee8e3010 00000002
>>>>>> 00000002 ee4d5f88 00000000
>>>>>> [    6.157669] 5ec0: 00000000 eeb8df00 000a82b4 c02c4278 00000002
>>>>>> ee476b00 eeb8df0c c01390ac
>>>>>> [    6.165828] 5ee0: 00000000 00000000 ee4e1f00 00000002 000a9540
>>>>>> ee4d5f88 c000f844 ee4d4000
>>>>>> [    6.173987] 5f00: 00000000 c00dbf70 000a82b4 c00093dc ee4d4000
>>>>>> ee4d5f78 ef328234 c0579bec
>>>>>> [    6.182146] 5f20: 00000001 00000001 ee4d5f3c 00000001 ee45e9c4
>>>>>> 00000001 000a82b4 c005ca74
>>>>>> [    6.190306] 5f40: ee45e9c4 00000002 000a9540 c005cad4 ee4e1f00
>>>>>> 00000002 000a9540 ee4d5f88
>>>>>> [    6.198465] 5f60: c000f844 c00dc770 00000000 00000000 ee4e1f00
>>>>>> ee4e1f00 00000002 000a9540
>>>>>> [    6.206624] 5f80: c000f844 c00dcf98 00000000 00000000 00000003
>>>>>> 000a7c40 00000001 000a9540
>>>>>> [    6.214783] 5fa0: 00000004 c000f680 000a7c40 00000001 00000001
>>>>>> 000a9540 00000002 00000000
>>>>>> [    6.222942] 5fc0: 000a7c40 00000001 000a9540 00000004 00000020
>>>>>> 000a82c8 000a8294 000a82b4
>>>>>> [    6.231102] 5fe0: 00000000 be8b1624 00012345 b6e94166 40000030
>>>>>> 00000001 00000000 00000000
>>>>>> [    6.239270] [<c02b1fb4>] (exynos_drm_fb_dma_addr) from [<c02c3cc4>]
>>>>>> (vidi_update_plane+0x4c/0xc4)
>>>>>> [    6.248122] [<c02c3cc4>] (vidi_update_plane) from [<c028ac14>]
>>>>>> (drm_atomic_helper_commit_planes+0x1f4/0x258)
>>>>>> [    6.257928] [<c028ac14>] (drm_atomic_helper_commit_planes) from
>>>>>> [<c02b08e4>] (exynos_atomic_commit_complete+0xe4/0x1c4)
>>>>>> [    6.268688] [<c02b08e4>] (exynos_atomic_commit_complete) from
>>>>>> [<c02b12b8>] (exynos_atomic_commit+0x180/0x1cc)
>>>>>> [    6.278584] [<c02b12b8>] (exynos_atomic_commit) from [<c028e0ec>]
>>>>>> (restore_fbdev_mode+0x260/0x290)
>>>>>> [    6.287525] [<c028e0ec>] (restore_fbdev_mode) from [<c028f8d4>]
>>>>>> (drm_fb_helper_restore_fbdev_mode_unlocked+0x30/0x74)
>>>>>> [    6.298111] [<c028f8d4>] (drm_fb_helper_restore_fbdev_mode_unlocked)
>>>>>> from [<c028f948>] (drm_fb_helper_set_par+0x30/0x54)
>>>>>> [    6.308961] [<c028f948>] (drm_fb_helper_set_par) from [<c028f864>]
>>>>>> (drm_fb_helper_hotplug_event+0x9c/0xdc)
>>>>>> [    6.318595] [<c028f864>] (drm_fb_helper_hotplug_event) from
>>>>>> [<c02853e4>] (drm_helper_hpd_irq_event+0xd4/0x160)
>>>>>> [    6.328578] [<c02853e4>] (drm_helper_hpd_irq_event) from
>>>>>> [<c02c4278>] (vidi_store_connection+0x94/0xcc)
>>>>>> [    6.337954] [<c02c4278>] (vidi_store_connection) from [<c01390ac>]
>>>>>> (kernfs_fop_write+0xb8/0x1bc)
>>>>>> [    6.346723] [<c01390ac>] (kernfs_fop_write) from [<c00dbf70>]
>>>>>> (__vfs_write+0x20/0xd8)
>>>>>> [    6.354531] [<c00dbf70>] (__vfs_write) from [<c00dc770>]
>>>>>> (vfs_write+0x90/0x164)
>>>>>> [    6.361821] [<c00dc770>] (vfs_write) from [<c00dcf98>]
>>>>>> (SyS_write+0x44/0x9c)
>>>>>> [    6.368855] [<c00dcf98>] (SyS_write) from [<c000f680>]
>>>>>> (ret_fast_syscall+0x0/0x3c)
>>>>>> [    6.376404] Code: eb0b17f1 eaffffe7 e3510003 d2811024 (d7900101)
>>>>>>
>>>>>> When vidi driver is intiated by triggering a connection sysfs file,
>>>>>> vidi driver tries modeset binding by calling drm_fb_helper_hotplug_event.
>>>>>> However, at this time it seems there is a case that plan->state->crtc
>>>>>> exists but plane->fb is NULL, which would be related to vidi driver.
>>>>>>
>>>>>> I just looked into this issue roughly so we would need to check this
>>>>>> issue in more details.
>>>>>>
>>>>>> Thanks,
>>>>>> Inki Dae
>>>>>>
>>>>>>> +    DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>>>>>           if (ctx->vblank_on)
>>>>>>>             schedule_work(&ctx->work);
>>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>>>> b/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>>>> index 47777be1a754..f40de82848dc 100644
>>>>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>>>> @@ -37,6 +37,7 @@
>>>>>>>       #include "exynos_drm_drv.h"
>>>>>>>     #include "exynos_drm_crtc.h"
>>>>>>> +#include "exynos_drm_fb.h"
>>>>>>>     #include "exynos_drm_plane.h"
>>>>>>>     #include "exynos_drm_iommu.h"
>>>>>>>     @@ -422,8 +423,8 @@ static void vp_video_buffer(struct
>>>>>>> mixer_context *ctx,
>>>>>>>             return;
>>>>>>>         }
>>>>>>>     -    luma_addr[0] = plane->dma_addr[0];
>>>>>>> -    chroma_addr[0] = plane->dma_addr[1];
>>>>>>> +    luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
>>>>>>> +    chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
>>>>>>>           if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
>>>>>>>             ctx->interlace = true;
>>>>>>> @@ -575,7 +576,7 @@ static void mixer_graph_buffer(struct
>>>>>>> mixer_context *ctx,
>>>>>>>         dst_y_offset = plane->crtc_y;
>>>>>>>           /* converting dma address base and source offset */
>>>>>>> -    dma_addr = plane->dma_addr[0]
>>>>>>> +    dma_addr = exynos_drm_fb_dma_addr(fb, 0)
>>>>>>>             + (plane->src_x * fb->bits_per_pixel >> 3)
>>>>>>>             + (plane->src_y * fb->pitches[0]);
>>>>>>>         src_x_offset = 0;
>>>>>>>
>>>>>>>
>>>>>>>

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

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

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

* Re: [PATCH v2 06/22] drm/exynos: move dma_addr attribute from exynos plane to exynos fb
  2015-12-14  9:15               ` Marek Szyprowski
@ 2015-12-14  9:43                 ` Inki Dae
  0 siblings, 0 replies; 40+ messages in thread
From: Inki Dae @ 2015-12-14  9:43 UTC (permalink / raw)
  To: Marek Szyprowski, Inki Dae
  Cc: Krzysztof Kozlowski, linux-samsung-soc,
	Bartlomiej Zolnierkiewicz, Seung-Woo Kim, DRI mailing list,
	Andrzej Hajda, Javier Martinez Canillas, Tobias Jakobi

Hi Marek,

2015년 12월 14일 18:15에 Marek Szyprowski 이(가) 쓴 글:
> Hi Inki,
> 
> On 2015-12-11 15:52, Inki Dae wrote:
>> 2015-12-11 20:27 GMT+09:00 Marek Szyprowski <m.szyprowski@samsung.com>:
>>> On 2015-12-11 10:57, Inki Dae wrote:
>>>> 2015년 12월 11일 18:26에 Marek Szyprowski 이(가) 쓴 글:
>>>>> On 2015-12-11 10:02, Inki Dae wrote:
>>>>>> I found out why NULL point access happened. That was incurred by below
>>>>>> your patch,
>>>>>> [PATCH] drm/exynos: move dma_addr attribute from exynos plane to exynos
>>>>>> fb
>>>>>>
>>>>>> When another crtc driver is hotplugged in runtime such as HDMI or VIDI,
>>>>>> the drm frambuffer object of fb_helper is set to the plane state of the
>>>>>> new crtc driver
>>>>>> so the driver should get the drm framebuffer object from the plane's
>>>>>> state or
>>>>>> exynos_plane->pending_fb which is set by exynos_plane_atomic_update
>>>>>> function.
>>>>>>
>>>>>> After that, I think the drm framebuffer should be set to drm plane as a
>>>>>> current fb
>>>>>> which would be scanned out.
>>>>>>
>>>>>> Anyway, I can fix it like below if you are ok.
>>>>>>
>>>>>> Thanks,
>>>>>> Inki Dae
>>>>>>
>>>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>> @@ -137,7 +137,7 @@ static void vidi_update_plane(struct exynos_drm_crtc
>>>>>> *crtc,
>>>>>>            if (ctx->suspended)
>>>>>>                    return;
>>>>>>     -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>>>>> +       addr = exynos_drm_fb_dma_addr(plane->pending_fb, 0);
>>>>>>            DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>>>>
>>>>>> +    plane->base.fb = plane->pending_fb;
>>>>> plane->base.fb should not be modified. I think that the following fix is
>>>>> more
>>>> Could you explain why plane->base.fb shouldn't be modified?
>>>
>>> All 'base' classes are modified by DRM core and there should be no need
>>> to modify them from the drivers.
>> Ok, If so - drm core updates plane->fb - then it's reasonable. But I
>> couldn't find the exact location where plane->fb is set to a fb to be
>> scanned out.
>> So could you let me know the exact location? it's not clear to me yet.
> 
> Setting plane->fb is wired somewhere in the atomic update logic, see
> __setplane_internal() function in drivers/gpu/drm/drm_crtc.c. Some more comments

This function wouldn't be related to what we are talking about. But...

> are also in the drm_atomic_clean_old_fb() function in drivers/gpu/drm/drm_atomic.c

Right. Seems that this function is called after exynos_plane_atomic_update function
call by atomic_update callback. So drm core updates plane->fb appropriately.

Thanks,
Inki Dae.

> However I don't know the exact call path.
> 
>>> I've checked this issue and the proper fix for is the following code:
>>>
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>> @@ -131,13 +131,14 @@ static void vidi_disable_vblank(struct exynos_drm_crtc
>>> *crtc)
>>>   static void vidi_update_plane(struct exynos_drm_crtc *crtc,
>>>                                struct exynos_drm_plane *plane)
>>>   {
>>> +       struct drm_plane_state *state = plane->base.state;
>>>          struct vidi_context *ctx = crtc->ctx;
>>>          dma_addr_t addr;
>>>
>>>          if (ctx->suspended)
>>>                  return;
>>>
>>> -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>> +       addr = exynos_drm_fb_dma_addr(state->fb, 0);
>>>          DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>
>>>          if (ctx->vblank_on)
>>>
>>>
>>> plane->base.fb is updated from the core once all crtc/plane atomic update
>>> calls finishes. The drivers should use the fb stored in plane->base.state.
>>> I've missed that VIDI driver doesn't get the fb and incorrectly used
>>> plane->base.fb instad of state->fb while updating the code.
>>>
>> Actually, I used state->fb instead of plane->pending_fb but in
>> exynos_plane_atomic_update function, plane->pending_fb is set to
>> state->fb.
>> That is why I commented like below,
>> " so the driver should get the drm framebuffer object from the plane's
>> state or exynos_plane->pending_fb which is set by
>> exynos_plane_atomic_update function."
>>
>> Anyway, using state->fb looks like more consistent with other drivers,
>> fimd, decon and mixer.
> 
> Thanks for applying my fix and merging this patch.
> 
>>>> In case that userspace requests setplane, plane->base.fb would be updated
>>>> after update_plane callback.
>>>> However, in other cases, I don't see how plane->base.fb could be updated.
>>>> In this case, I think vendor specific drivers would need to update it as a
>>>> current fb to be scanned out like other some drivers did.
>>>> Of course, it may be possible for drm core part to take care of it
>>>> appropriately later.
>>>>
>>>> Thanks,
>>>> Inki Dae
>>>>
>>>>> appropriate:
>>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>> @@ -132,12 +132,13 @@ static void vidi_update_plane(struct
>>>>> exynos_drm_crtc *crtc,
>>>>>                                 struct exynos_drm_plane *plane)
>>>>>    {
>>>>>           struct vidi_context *ctx = crtc->ctx;
>>>>> -       dma_addr_t addr;
>>>>> +       dma_addr_t addr = 0;
>>>>>
>>>>>           if (ctx->suspended)
>>>>>                   return;
>>>>>
>>>>> -       addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>>>> +       if (plane->base.fb)
>>>>> +               addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>>>>           DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>>>
>>>>>           if (ctx->vblank_on)
>>>>>
>>>>> I will investigate the case of NULL plane->state.fb, because it might be
>>>>> relevant
>>>>> to other crtc drivers as well.
>>>>>
>>>>>
>>>>>>              if (ctx->vblank_on)
>>>>>>
>>>>>>
>>>>>> 2015년 12월 10일 22:05에 Inki Dae 이(가) 쓴 글:
>>>>>>> 2015년 11월 30일 22:53에 Marek Szyprowski 이(가) 쓴 글:
>>>>>>>> DMA address is a framebuffer attribute and the right place for it is
>>>>>>>> exynos_drm_framebuffer not exynos_drm_plane. This patch also
>>>>>>>> introduces
>>>>>>>> helper function for getting dma address of the given framebuffer.
>>>>>>>>
>>>>>>>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>>>>>>>> Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>>>>>>>> ---
>>>>>>>>     drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 13 ++++++++-----
>>>>>>>>     drivers/gpu/drm/exynos/exynos7_drm_decon.c    | 16 +++++++++-------
>>>>>>>>     drivers/gpu/drm/exynos/exynos_drm_drv.h       |  3 ---
>>>>>>>>     drivers/gpu/drm/exynos/exynos_drm_fb.c        | 16 ++++++----------
>>>>>>>>     drivers/gpu/drm/exynos/exynos_drm_fb.h        |  3 +--
>>>>>>>>     drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 10 ++++++----
>>>>>>>>     drivers/gpu/drm/exynos/exynos_drm_plane.c     | 18
>>>>>>>> ------------------
>>>>>>>>     drivers/gpu/drm/exynos/exynos_drm_vidi.c      |  5 ++++-
>>>>>>>>     drivers/gpu/drm/exynos/exynos_mixer.c         |  7 ++++---
>>>>>>>>     9 files changed, 38 insertions(+), 53 deletions(-)
>>>>>>>>
>>>>>>> <--snip-->
>>>>>>>
>>>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>>>> b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>>>> index 669362c53f49..3ce141236fad 100644
>>>>>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>>>>>>> @@ -24,6 +24,7 @@
>>>>>>>>       #include "exynos_drm_drv.h"
>>>>>>>>     #include "exynos_drm_crtc.h"
>>>>>>>> +#include "exynos_drm_fb.h"
>>>>>>>>     #include "exynos_drm_plane.h"
>>>>>>>>     #include "exynos_drm_vidi.h"
>>>>>>>>     @@ -126,11 +127,13 @@ static void vidi_update_plane(struct
>>>>>>>> exynos_drm_crtc *crtc,
>>>>>>>>                       struct exynos_drm_plane *plane)
>>>>>>>>     {
>>>>>>>>         struct vidi_context *ctx = crtc->ctx;
>>>>>>>> +    dma_addr_t addr;
>>>>>>>>           if (ctx->suspended)
>>>>>>>>             return;
>>>>>>>>     -    DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
>>>>>>>> +    addr = exynos_drm_fb_dma_addr(plane->base.fb, 0);
>>>>>>> At this point, plane->base.fb is NULL so null pointer access happens
>>>>>>> like below,
>>>>>>>
>>>>>>> [    5.969422] Unable to handle kernel NULL pointer dereference at
>>>>>>> virtual address 00000090
>>>>>>> [    5.977481] pgd = ee590000
>>>>>>> [    5.980142] [00000090] *pgd=6e526831, *pte=00000000, *ppte=00000000
>>>>>>> [    5.986347] Internal error: Oops: 17 [#1] PREEMPT SMP ARM
>>>>>>> [    5.991712] Modules linked in:
>>>>>>> [    5.994770] CPU: 3 PID: 1598 Comm: sh Not tainted
>>>>>>> 4.4.0-rc3-00052-gc60d7e2-dirty #199
>>>>>>> [    6.002565] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
>>>>>>> [    6.008647] task: ef328000 ti: ee4d4000 task.ti: ee4d4000
>>>>>>> [    6.014053] PC is at exynos_drm_fb_dma_addr+0x8/0x14
>>>>>>> [    6.018990] LR is at vidi_update_plane+0x4c/0xc4
>>>>>>> [    6.023581] pc : [<c02b1fb4>]    lr : [<c02c3cc4>]    psr: 80000013
>>>>>>> [    6.023581] sp : ee4d5d90  ip : 00000001  fp : 00000000
>>>>>>> [    6.035029] r10: 00000000  r9 : c05b965c  r8 : ee813e00
>>>>>>> [    6.040241] r7 : 00000000  r6 : ee8e3330  r5 : 00000000  r4 :
>>>>>>> ee8e3010
>>>>>>> [    6.046749] r3 : 00000000  r2 : 00000000  r1 : 00000024  r0 :
>>>>>>> 00000000
>>>>>>> [    6.053264] Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM
>>>>>>> Segment none
>>>>>>> [    6.060379] Control: 10c5387d  Table: 6e59004a  DAC: 00000051
>>>>>>> [    6.066107] Process sh (pid: 1598, stack limit = 0xee4d4210)
>>>>>>> [    6.071748] Stack: (0xee4d5d90 to 0xee4d6000)
>>>>>>> [    6.076100] 5d80:                                     00000000
>>>>>>> ee813300 ee476e40 00000005
>>>>>>> [    6.084236] 5da0: ee8e3330 c028ac14 00000008 ee476e40 ee476fc0
>>>>>>> ef3b3800 ee476fc0 eeb3e380
>>>>>>> [    6.092395] 5dc0: 00000002 c02b08e4 00000000 eeb3e3a4 ee476fc0
>>>>>>> ee476e40 ef3b3800 eeb3e380
>>>>>>> [    6.100554] 5de0: 00000002 c02b12b8 ee854400 00000000 00000001
>>>>>>> ee8501a8 00000000 ee476e40
>>>>>>> [    6.108714] 5e00: ef3b3800 00000001 ee476e40 00000050 ee850c80
>>>>>>> 00000001 ee476e40 ef3b3aac
>>>>>>> [    6.116873] 5e20: 00000002 000000ff 00000000 c028e0ec 000a82b4
>>>>>>> c02acc50 ee8e36a0 ee476c80
>>>>>>> [    6.125032] 5e40: ef3b3aac ef3b3800 ee476c9c ee850c80 ef3b3800
>>>>>>> ef3b3800 ef3b3800 ef3b398c
>>>>>>> [    6.133191] 5e60: c088c390 00000002 000a82b4 c028f8d4 00000000
>>>>>>> ef3b3800 ef0f4300 c028f948
>>>>>>> [    6.141350] 5e80: ee850c80 c028f864 ef3b3a84 00000001 ef3b3a90
>>>>>>> c02853e4 00000001 00000000
>>>>>>> [    6.149509] 5ea0: 000a82b4 ee4d5ec0 00000002 ee8e3010 00000002
>>>>>>> 00000002 ee4d5f88 00000000
>>>>>>> [    6.157669] 5ec0: 00000000 eeb8df00 000a82b4 c02c4278 00000002
>>>>>>> ee476b00 eeb8df0c c01390ac
>>>>>>> [    6.165828] 5ee0: 00000000 00000000 ee4e1f00 00000002 000a9540
>>>>>>> ee4d5f88 c000f844 ee4d4000
>>>>>>> [    6.173987] 5f00: 00000000 c00dbf70 000a82b4 c00093dc ee4d4000
>>>>>>> ee4d5f78 ef328234 c0579bec
>>>>>>> [    6.182146] 5f20: 00000001 00000001 ee4d5f3c 00000001 ee45e9c4
>>>>>>> 00000001 000a82b4 c005ca74
>>>>>>> [    6.190306] 5f40: ee45e9c4 00000002 000a9540 c005cad4 ee4e1f00
>>>>>>> 00000002 000a9540 ee4d5f88
>>>>>>> [    6.198465] 5f60: c000f844 c00dc770 00000000 00000000 ee4e1f00
>>>>>>> ee4e1f00 00000002 000a9540
>>>>>>> [    6.206624] 5f80: c000f844 c00dcf98 00000000 00000000 00000003
>>>>>>> 000a7c40 00000001 000a9540
>>>>>>> [    6.214783] 5fa0: 00000004 c000f680 000a7c40 00000001 00000001
>>>>>>> 000a9540 00000002 00000000
>>>>>>> [    6.222942] 5fc0: 000a7c40 00000001 000a9540 00000004 00000020
>>>>>>> 000a82c8 000a8294 000a82b4
>>>>>>> [    6.231102] 5fe0: 00000000 be8b1624 00012345 b6e94166 40000030
>>>>>>> 00000001 00000000 00000000
>>>>>>> [    6.239270] [<c02b1fb4>] (exynos_drm_fb_dma_addr) from [<c02c3cc4>]
>>>>>>> (vidi_update_plane+0x4c/0xc4)
>>>>>>> [    6.248122] [<c02c3cc4>] (vidi_update_plane) from [<c028ac14>]
>>>>>>> (drm_atomic_helper_commit_planes+0x1f4/0x258)
>>>>>>> [    6.257928] [<c028ac14>] (drm_atomic_helper_commit_planes) from
>>>>>>> [<c02b08e4>] (exynos_atomic_commit_complete+0xe4/0x1c4)
>>>>>>> [    6.268688] [<c02b08e4>] (exynos_atomic_commit_complete) from
>>>>>>> [<c02b12b8>] (exynos_atomic_commit+0x180/0x1cc)
>>>>>>> [    6.278584] [<c02b12b8>] (exynos_atomic_commit) from [<c028e0ec>]
>>>>>>> (restore_fbdev_mode+0x260/0x290)
>>>>>>> [    6.287525] [<c028e0ec>] (restore_fbdev_mode) from [<c028f8d4>]
>>>>>>> (drm_fb_helper_restore_fbdev_mode_unlocked+0x30/0x74)
>>>>>>> [    6.298111] [<c028f8d4>] (drm_fb_helper_restore_fbdev_mode_unlocked)
>>>>>>> from [<c028f948>] (drm_fb_helper_set_par+0x30/0x54)
>>>>>>> [    6.308961] [<c028f948>] (drm_fb_helper_set_par) from [<c028f864>]
>>>>>>> (drm_fb_helper_hotplug_event+0x9c/0xdc)
>>>>>>> [    6.318595] [<c028f864>] (drm_fb_helper_hotplug_event) from
>>>>>>> [<c02853e4>] (drm_helper_hpd_irq_event+0xd4/0x160)
>>>>>>> [    6.328578] [<c02853e4>] (drm_helper_hpd_irq_event) from
>>>>>>> [<c02c4278>] (vidi_store_connection+0x94/0xcc)
>>>>>>> [    6.337954] [<c02c4278>] (vidi_store_connection) from [<c01390ac>]
>>>>>>> (kernfs_fop_write+0xb8/0x1bc)
>>>>>>> [    6.346723] [<c01390ac>] (kernfs_fop_write) from [<c00dbf70>]
>>>>>>> (__vfs_write+0x20/0xd8)
>>>>>>> [    6.354531] [<c00dbf70>] (__vfs_write) from [<c00dc770>]
>>>>>>> (vfs_write+0x90/0x164)
>>>>>>> [    6.361821] [<c00dc770>] (vfs_write) from [<c00dcf98>]
>>>>>>> (SyS_write+0x44/0x9c)
>>>>>>> [    6.368855] [<c00dcf98>] (SyS_write) from [<c000f680>]
>>>>>>> (ret_fast_syscall+0x0/0x3c)
>>>>>>> [    6.376404] Code: eb0b17f1 eaffffe7 e3510003 d2811024 (d7900101)
>>>>>>>
>>>>>>> When vidi driver is intiated by triggering a connection sysfs file,
>>>>>>> vidi driver tries modeset binding by calling drm_fb_helper_hotplug_event.
>>>>>>> However, at this time it seems there is a case that plan->state->crtc
>>>>>>> exists but plane->fb is NULL, which would be related to vidi driver.
>>>>>>>
>>>>>>> I just looked into this issue roughly so we would need to check this
>>>>>>> issue in more details.
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Inki Dae
>>>>>>>
>>>>>>>> +    DRM_DEBUG_KMS("dma_addr = %pad\n", &addr);
>>>>>>>>           if (ctx->vblank_on)
>>>>>>>>             schedule_work(&ctx->work);
>>>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>>>>> b/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>>>>> index 47777be1a754..f40de82848dc 100644
>>>>>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
>>>>>>>> @@ -37,6 +37,7 @@
>>>>>>>>       #include "exynos_drm_drv.h"
>>>>>>>>     #include "exynos_drm_crtc.h"
>>>>>>>> +#include "exynos_drm_fb.h"
>>>>>>>>     #include "exynos_drm_plane.h"
>>>>>>>>     #include "exynos_drm_iommu.h"
>>>>>>>>     @@ -422,8 +423,8 @@ static void vp_video_buffer(struct
>>>>>>>> mixer_context *ctx,
>>>>>>>>             return;
>>>>>>>>         }
>>>>>>>>     -    luma_addr[0] = plane->dma_addr[0];
>>>>>>>> -    chroma_addr[0] = plane->dma_addr[1];
>>>>>>>> +    luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
>>>>>>>> +    chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
>>>>>>>>           if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
>>>>>>>>             ctx->interlace = true;
>>>>>>>> @@ -575,7 +576,7 @@ static void mixer_graph_buffer(struct
>>>>>>>> mixer_context *ctx,
>>>>>>>>         dst_y_offset = plane->crtc_y;
>>>>>>>>           /* converting dma address base and source offset */
>>>>>>>> -    dma_addr = plane->dma_addr[0]
>>>>>>>> +    dma_addr = exynos_drm_fb_dma_addr(fb, 0)
>>>>>>>>             + (plane->src_x * fb->bits_per_pixel >> 3)
>>>>>>>>             + (plane->src_y * fb->pitches[0]);
>>>>>>>>         src_x_offset = 0;
>>>>>>>>
>>>>>>>>
>>>>>>>>
> 
> Best regards
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem
  2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
                   ` (21 preceding siblings ...)
  2015-11-30 13:53 ` [PATCH v2 22/22] drm/exynos: add support for plane rotation, scalling and colospace convesion Marek Szyprowski
@ 2016-03-15 14:46 ` Tobias Jakobi
  22 siblings, 0 replies; 40+ messages in thread
From: Tobias Jakobi @ 2016-03-15 14:46 UTC (permalink / raw)
  To: Marek Szyprowski, dri-devel, linux-samsung-soc
  Cc: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Andrzej Hajda,
	Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz, Gustavo Padovan,
	Javier Martinez Canillas

Hello all,

I wanted to ask if there has been any progress since last time. Also I
was wondering if it would be feasible to just fixup the IPP API and then
go from there (instead of trying to do automagic behind the scenes).
Marek has pointed out that currently the API has some major flaws and
the wording of the objects used (e.g. IPP property) probably isn't
really the best.

However there don't seem to be any upstream users, so again breaking the
API should be fine?

I'm still interested in using the framework for a vo backend for the mpv
media player.


With best wishes,
Tobias


Marek Szyprowski wrote:
> Dear All,
> 
> This patch series introduces a new life into Exynos IPP (Image Post
> Processing) subsystem by integrating it (transparently for userspace
> applications) with Exynos DRM core plane management. This means that all
> CRTC drivers transparently get support for standard features of IPP
> subsystem like rotation, scaling and color space conversion.
> 
> Support for features not supported natively by CRTC drivers is
> implemented with a help of temporary framebuffers, where image data is
> processed by IPP subsystem before performing the scanout by a CRTC driver.
> 
> This is second version of this patchset. The initial version is available
> here:
> http://thread.gmane.org/gmane.linux.kernel.samsung-soc/49743
> 
> The main change since v1 is support for color space conversion and minor
> fixes in the preparation patches (added support for native scaling in
> Exynos Video Processor module).
> 
> This feature is 'experimental'. From the initial discussion I see that
> there is no consensus if this feature should be integrated seamplessly
> in Exynos DRM core or provided by a separate API. This will be further
> discussed.
> 
> However, I would like to ask for merging patches 1-15, which are pure
> bugfixes and code cleanups. The patches are based on top of current
> exynos-drm-next branch.
> 
> Best regards
> Marek Szyprowski
> Samsung R&D Institute Poland
> 
> 
> Patch summary:
> 
> Marek Szyprowski (17):
>   drm/exynos: rotator: convert to common clock framework
>   drm/exynos: exynos7-decon: remove excessive check
>   drm/exynos: move dma_addr attribute from exynos plane to exynos fb
>   drm/exynos: introduce exynos_drm_plane_state structure
>   drm/exynos: mixer: use crtc->state->adjusted_mode instead of
>     crtc->mode
>   drm/exynos: mixer: enable video overlay plane only when VP is
>     available
>   drm/exynos: introduce exynos_drm_plane_config structure
>   drm/exynos: add generic check for plane state
>   drm/exynos: mixer: use ratio precalculated in exynos_state
>   drm/exynos: fix clipping when scaling is enabled
>   drm/exynos: fimd: fix dma burst size setting for small plane size
>   drm/exynos: gem: remove old unused prototypes
>   drm/exynos: add fb pointer to exynos_drm_plane_state
>   drm/exynos: gem: set default alignment for dumb GEM buffers
>   drm/exynos: gem: simplify access to exynos gem object
>   drm/exynos: ipp: make framework context global
>   drm/exynos: add support for plane rotation, scalling and colospace
>     convesion
> 
> Seung-Woo Kim (5):
>   drm/exynos: gsc: prepare and unprepare gsc clock
>   drm/exynos: gsc: fix wrong pm_runtime state
>   drm/exynos: gsc: add device tree support and remove usage of static
>     mappings
>   drm/exynos: fix to calculate offset of each plane for ipp fimc
>   drm/exynos: fix to calculate offset of each plane for ipp gsc
> 
>  .../devicetree/bindings/media/exynos5-gsc.txt      |   4 +
>  drivers/gpu/drm/exynos/Kconfig                     |  10 +-
>  drivers/gpu/drm/exynos/Makefile                    |   1 +
>  drivers/gpu/drm/exynos/exynos5433_drm_decon.c      |  48 ++-
>  drivers/gpu/drm/exynos/exynos7_drm_decon.c         |  68 ++--
>  drivers/gpu/drm/exynos/exynos_drm_drv.h            |  96 ++++--
>  drivers/gpu/drm/exynos/exynos_drm_fb.c             |  16 +-
>  drivers/gpu/drm/exynos/exynos_drm_fb.h             |   3 +-
>  drivers/gpu/drm/exynos/exynos_drm_fimc.c           | 106 ++++++
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c           |  88 ++---
>  drivers/gpu/drm/exynos/exynos_drm_g2d.c            |  48 ++-
>  drivers/gpu/drm/exynos/exynos_drm_gem.c            |  54 +--
>  drivers/gpu/drm/exynos/exynos_drm_gem.h            |  51 +--
>  drivers/gpu/drm/exynos/exynos_drm_gsc.c            | 151 ++++++++-
>  drivers/gpu/drm/exynos/exynos_drm_ipp.c            | 240 +++++++++++---
>  drivers/gpu/drm/exynos/exynos_drm_ipp.h            |   8 +-
>  drivers/gpu/drm/exynos/exynos_drm_plane.c          | 237 ++++++++-----
>  drivers/gpu/drm/exynos/exynos_drm_plane.h          |   7 +-
>  drivers/gpu/drm/exynos/exynos_drm_plane_ipp.c      | 369 +++++++++++++++++++++
>  drivers/gpu/drm/exynos/exynos_drm_plane_ipp.h      |  73 ++++
>  drivers/gpu/drm/exynos/exynos_drm_rotator.c        |   4 +-
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c           |  30 +-
>  drivers/gpu/drm/exynos/exynos_mixer.c              | 129 ++++---
>  drivers/gpu/drm/exynos/regs-gsc.h                  |   4 +-
>  24 files changed, 1375 insertions(+), 470 deletions(-)
>  create mode 100644 drivers/gpu/drm/exynos/exynos_drm_plane_ipp.c
>  create mode 100644 drivers/gpu/drm/exynos/exynos_drm_plane_ipp.h
> 

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

end of thread, other threads:[~2016-03-15 14:46 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-30 13:53 [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 01/22] drm/exynos: gsc: prepare and unprepare gsc clock Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 02/22] drm/exynos: gsc: fix wrong pm_runtime state Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 03/22] drm/exynos: gsc: add device tree support and remove usage of static mappings Marek Szyprowski
2015-12-10  6:48   ` Inki Dae
2015-12-10  6:55     ` Krzysztof Kozlowski
2015-11-30 13:53 ` [PATCH v2 04/22] drm/exynos: rotator: convert to common clock framework Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 05/22] drm/exynos: exynos7-decon: remove excessive check Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 06/22] drm/exynos: move dma_addr attribute from exynos plane to exynos fb Marek Szyprowski
2015-12-10 13:05   ` Inki Dae
2015-12-11  9:02     ` Inki Dae
2015-12-11  9:26       ` Marek Szyprowski
2015-12-11  9:57         ` Inki Dae
2015-12-11 11:27           ` Marek Szyprowski
2015-12-11 14:52             ` Inki Dae
2015-12-14  9:15               ` Marek Szyprowski
2015-12-14  9:43                 ` Inki Dae
2015-11-30 13:53 ` [PATCH v2 07/22] drm/exynos: introduce exynos_drm_plane_state structure Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 08/22] drm/exynos: mixer: use crtc->state->adjusted_mode instead of crtc->mode Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 09/22] drm/exynos: mixer: enable video overlay plane only when VP is available Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 10/22] drm/exynos: introduce exynos_drm_plane_config structure Marek Szyprowski
2015-12-10 11:47   ` Inki Dae
2015-11-30 13:53 ` [PATCH v2 11/22] drm/exynos: add generic check for plane state Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 12/22] drm/exynos: mixer: use ratio precalculated in exynos_state Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 13/22] drm/exynos: fix clipping when scaling is enabled Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 14/22] drm/exynos: fimd: fix dma burst size setting for small plane size Marek Szyprowski
2015-11-30 15:40   ` Daniel Stone
2015-12-10 11:35   ` Inki Dae
2015-12-10 12:59     ` Marek Szyprowski
2015-12-10 15:36       ` Daniel Stone
2015-12-11  9:04       ` Inki Dae
2015-11-30 13:53 ` [PATCH v2 15/22] drm/exynos: gem: remove old unused prototypes Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 16/22] drm/exynos: add fb pointer to exynos_drm_plane_state Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 17/22] drm/exynos: gem: set default alignment for dumb GEM buffers Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 18/22] drm/exynos: fix to calculate offset of each plane for ipp fimc Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 19/22] drm/exynos: fix to calculate offset of each plane for ipp gsc Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 20/22] drm/exynos: gem: simplify access to exynos gem object Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 21/22] drm/exynos: ipp: make framework context global Marek Szyprowski
2015-11-30 13:53 ` [PATCH v2 22/22] drm/exynos: add support for plane rotation, scalling and colospace convesion Marek Szyprowski
2016-03-15 14:46 ` [PATCH v2 00/22] Exynos DRM: new life of IPP (Image Post Processing) subsystem Tobias Jakobi

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.