linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/9] drm: atmel-hlcdc: various fixes/improvements
@ 2016-03-16 13:57 Boris Brezillon
  2016-03-16 13:57 ` [PATCH v2 1/9] drm: atmel-hlcdc: add a ->cleanup_fb() operation Boris Brezillon
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Boris Brezillon @ 2016-03-16 13:57 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, dri-devel
  Cc: Nicolas Ferre, Jean-Christophe Plagniol-Villard,
	Alexandre Belloni, linux-arm-kernel, linux-kernel,
	Boris Brezillon

Hello,

This series is a collection of fixes and improvements for the
atmel-hlcdc driver.

The main feature added here is the support for external RGB -> XXX
bridges (patch 6 and 7).

The first patch is a fix preventing a potential memory leak.
Patch 2 is adding support for asynchronous mode setting, which was
supported before the migration to atomic mode setting.

Patch 3 is just a minor fix to expose the real encoder and connector
types (we are currently exposing an LVDS encoder/connector, which is
wrong since the display controller output the pixel stream in raw
RGB).

Patch 4 is removing useless fields and functions which were left
when moving to atomic modesetting.

Patch 8 is just a cosmetic patch moving the mode checking code
from ->atomic_check() to ->mode_fixup().

Patch 9 is increasing HLCDC bandwidth by making use of the two AHB
interfaces.

Best Regards,

Boris

Changes since v1:
- Add Nicolas Reviewed/Teste/Acked-by tags
- Add a patch to increase HLCDC bandwidth by using both AHB interfaces

Boris Brezillon (9):
  drm: atmel-hlcdc: add a ->cleanup_fb() operation
  drm: atmel-hlcdc: support asynchronous atomic commit operations
  drm: atmel-hlcdc: fix connector and encoder types
  drm: atmel-hlcdc: remove leftovers from atomic mode setting migration
  drm: atmel-hlcdc: support extended timing ranges on sama5d4 and
    sama5d2
  drm: atmel-hlcdc: move output mode selection in CRTC implementation
  drm: atmel-hlcdc: rework the output code to support drm bridges
  drm: atmel-hlcdc: check display mode validity in crtc->mode_fixup()
  drm: atmel-hlcdc: route DMA accesses through AHB interfaces

 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c   | 154 +++++++++++++-
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c     | 123 ++++++++++-
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h     |  17 ++
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 249 ++++++++++-------------
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c  |  65 +++++-
 5 files changed, 447 insertions(+), 161 deletions(-)

-- 
2.5.0

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

* [PATCH v2 1/9] drm: atmel-hlcdc: add a ->cleanup_fb() operation
  2016-03-16 13:57 [PATCH v2 0/9] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
@ 2016-03-16 13:57 ` Boris Brezillon
  2016-03-16 15:17   ` Daniel Vetter
  2016-03-16 13:57 ` [PATCH v2 2/9] drm: atmel-hlcdc: support asynchronous atomic commit operations Boris Brezillon
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Boris Brezillon @ 2016-03-16 13:57 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, dri-devel
  Cc: Nicolas Ferre, Jean-Christophe Plagniol-Villard,
	Alexandre Belloni, linux-arm-kernel, linux-kernel,
	Boris Brezillon

Add a ->cleanup_fb() operation to avoid memory leaks when the atomic
operation is interrupted after the ->prepare_fb() call.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Fixes 2389fc1 ("drm: atmel-hlcdc: Atomic mode-setting conversion")
Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h    |  2 ++
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 22 +++++++++++++++++++---
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
index fed517f..ec64140 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
@@ -81,11 +81,13 @@ struct atmel_hlcdc_plane_properties {
  * @layer: HLCDC layer structure
  * @properties: pointer to the property definitions structure
  * @rotation: current rotation status
+ * @prepared: flagging the plane has prepared for an atomic update
  */
 struct atmel_hlcdc_plane {
 	struct drm_plane base;
 	struct atmel_hlcdc_layer layer;
 	struct atmel_hlcdc_plane_properties *properties;
+	bool prepared;
 };
 
 static inline struct atmel_hlcdc_plane *
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index 1ffe9c3..35027d0 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -715,11 +715,25 @@ static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
 					const struct drm_plane_state *new_state)
 {
 	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
+	int ret;
 
-	if (!new_state->fb)
-		return 0;
+	ret = atmel_hlcdc_layer_update_start(&plane->layer);
+	if (!ret)
+		plane->prepared = true;
+
+	return ret;
+}
+
+static void atmel_hlcdc_plane_cleanup_fb(struct drm_plane *p,
+				const struct drm_plane_state *old_state)
+{
+	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
+
+	if (!plane->prepared)
+		return;
 
-	return atmel_hlcdc_layer_update_start(&plane->layer);
+	atmel_hlcdc_layer_update_rollback(&plane->layer);
+	plane->prepared = false;
 }
 
 static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
@@ -739,6 +753,7 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
 	atmel_hlcdc_plane_update_disc_area(plane, state);
 
 	atmel_hlcdc_layer_update_commit(&plane->layer);
+	plane->prepared = false;
 }
 
 static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p,
@@ -844,6 +859,7 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
 
 static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
 	.prepare_fb = atmel_hlcdc_plane_prepare_fb,
+	.cleanup_fb = atmel_hlcdc_plane_cleanup_fb,
 	.atomic_check = atmel_hlcdc_plane_atomic_check,
 	.atomic_update = atmel_hlcdc_plane_atomic_update,
 	.atomic_disable = atmel_hlcdc_plane_atomic_disable,
-- 
2.5.0

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

* [PATCH v2 2/9] drm: atmel-hlcdc: support asynchronous atomic commit operations
  2016-03-16 13:57 [PATCH v2 0/9] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
  2016-03-16 13:57 ` [PATCH v2 1/9] drm: atmel-hlcdc: add a ->cleanup_fb() operation Boris Brezillon
@ 2016-03-16 13:57 ` Boris Brezillon
  2016-03-16 13:57 ` [PATCH v2 3/9] drm: atmel-hlcdc: fix connector and encoder types Boris Brezillon
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Boris Brezillon @ 2016-03-16 13:57 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, dri-devel
  Cc: Nicolas Ferre, Jean-Christophe Plagniol-Villard,
	Alexandre Belloni, linux-arm-kernel, linux-kernel,
	Boris Brezillon

drm_atomic_helper_commit() does not support asynchronous commits.
Replace it by a specific commit function supporting these kind of requests.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 94 +++++++++++++++++++++++++++-
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h |  5 ++
 2 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 3d8d164..851b4a0 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -427,11 +427,102 @@ static void atmel_hlcdc_fb_output_poll_changed(struct drm_device *dev)
 	}
 }
 
+struct atmel_hlcdc_dc_commit {
+	struct work_struct work;
+	struct drm_device *dev;
+	struct drm_atomic_state *state;
+};
+
+static void
+atmel_hlcdc_dc_atomic_complete(struct atmel_hlcdc_dc_commit *commit)
+{
+	struct drm_device *dev = commit->dev;
+	struct atmel_hlcdc_dc *dc = dev->dev_private;
+	struct drm_atomic_state *old_state = commit->state;
+
+	/* Apply the atomic update. */
+	drm_atomic_helper_commit_modeset_disables(dev, old_state);
+	drm_atomic_helper_commit_planes(dev, old_state, false);
+	drm_atomic_helper_commit_modeset_enables(dev, old_state);
+
+	drm_atomic_helper_wait_for_vblanks(dev, old_state);
+
+	drm_atomic_helper_cleanup_planes(dev, old_state);
+
+	drm_atomic_state_free(old_state);
+
+	/* Complete the commit, wake up any waiter. */
+	spin_lock(&dc->commit.wait.lock);
+	dc->commit.pending = false;
+	wake_up_all_locked(&dc->commit.wait);
+	spin_unlock(&dc->commit.wait.lock);
+
+	kfree(commit);
+}
+
+static void atmel_hlcdc_dc_atomic_work(struct work_struct *work)
+{
+	struct atmel_hlcdc_dc_commit *commit =
+		container_of(work, struct atmel_hlcdc_dc_commit, work);
+
+	atmel_hlcdc_dc_atomic_complete(commit);
+}
+
+static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
+					struct drm_atomic_state *state,
+					bool async)
+{
+	struct atmel_hlcdc_dc *dc = dev->dev_private;
+	struct atmel_hlcdc_dc_commit *commit;
+	int ret;
+
+	ret = drm_atomic_helper_prepare_planes(dev, state);
+	if (ret)
+		return ret;
+
+	/* Allocate the commit object. */
+	commit = kzalloc(sizeof(*commit), GFP_KERNEL);
+	if (!commit) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	INIT_WORK(&commit->work, atmel_hlcdc_dc_atomic_work);
+	commit->dev = dev;
+	commit->state = state;
+
+	spin_lock(&dc->commit.wait.lock);
+	ret = wait_event_interruptible_locked(dc->commit.wait,
+					      !dc->commit.pending);
+	if (ret == 0)
+		dc->commit.pending = true;
+	spin_unlock(&dc->commit.wait.lock);
+
+	if (ret) {
+		kfree(commit);
+		goto error;
+	}
+
+	/* Swap the state, this is the point of no return. */
+	drm_atomic_helper_swap_state(dev, state);
+
+	if (async)
+		queue_work(dc->wq, &commit->work);
+	else
+		atmel_hlcdc_dc_atomic_complete(commit);
+
+	return 0;
+
+error:
+	drm_atomic_helper_cleanup_planes(dev, state);
+	return ret;
+}
+
 static const struct drm_mode_config_funcs mode_config_funcs = {
 	.fb_create = atmel_hlcdc_fb_create,
 	.output_poll_changed = atmel_hlcdc_fb_output_poll_changed,
 	.atomic_check = drm_atomic_helper_check,
-	.atomic_commit = drm_atomic_helper_commit,
+	.atomic_commit = atmel_hlcdc_dc_atomic_commit,
 };
 
 static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev)
@@ -509,6 +600,7 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev)
 	if (!dc->wq)
 		return -ENOMEM;
 
+	init_waitqueue_head(&dc->commit.wait);
 	dc->desc = match->data;
 	dc->hlcdc = dev_get_drvdata(dev->dev->parent);
 	dev->dev_private = dc;
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
index ec64140..53b4488 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
@@ -130,6 +130,7 @@ struct atmel_hlcdc_planes {
  * @planes: instantiated planes
  * @layers: active HLCDC layer
  * @wq: display controller workqueue
+ * @commit: used for async commit handling
  */
 struct atmel_hlcdc_dc {
 	const struct atmel_hlcdc_dc_desc *desc;
@@ -139,6 +140,10 @@ struct atmel_hlcdc_dc {
 	struct atmel_hlcdc_planes *planes;
 	struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS];
 	struct workqueue_struct *wq;
+	struct {
+		wait_queue_head_t wait;
+		bool pending;
+	} commit;
 };
 
 extern struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats;
-- 
2.5.0

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

* [PATCH v2 3/9] drm: atmel-hlcdc: fix connector and encoder types
  2016-03-16 13:57 [PATCH v2 0/9] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
  2016-03-16 13:57 ` [PATCH v2 1/9] drm: atmel-hlcdc: add a ->cleanup_fb() operation Boris Brezillon
  2016-03-16 13:57 ` [PATCH v2 2/9] drm: atmel-hlcdc: support asynchronous atomic commit operations Boris Brezillon
@ 2016-03-16 13:57 ` Boris Brezillon
  2016-03-16 13:57 ` [PATCH v2 4/9] drm: atmel-hlcdc: remove leftovers from atomic mode setting migration Boris Brezillon
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Boris Brezillon @ 2016-03-16 13:57 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, dri-devel
  Cc: Nicolas Ferre, Jean-Christophe Plagniol-Villard,
	Alexandre Belloni, linux-arm-kernel, linux-kernel,
	Boris Brezillon

The hlcdc IP keep the pixel stream in raw RGB mode, and does not provide
any specific connector. Since DRM_MODE_CONNECTOR_RAW_RGB does not exist,
use DRM_MODE_CONNECTOR_Unknown.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index 0f7ec01..49494e9 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
@@ -256,7 +256,7 @@ static int atmel_hlcdc_create_panel_output(struct drm_device *dev,
 			       &atmel_hlcdc_panel_encoder_helper_funcs);
 	ret = drm_encoder_init(dev, &panel->base.encoder,
 			       &atmel_hlcdc_panel_encoder_funcs,
-			       DRM_MODE_ENCODER_LVDS, NULL);
+			       DRM_MODE_ENCODER_NONE, NULL);
 	if (ret)
 		return ret;
 
@@ -266,7 +266,7 @@ static int atmel_hlcdc_create_panel_output(struct drm_device *dev,
 				 &atmel_hlcdc_panel_connector_helper_funcs);
 	ret = drm_connector_init(dev, &panel->base.connector,
 				 &atmel_hlcdc_panel_connector_funcs,
-				 DRM_MODE_CONNECTOR_LVDS);
+				 DRM_MODE_CONNECTOR_Unknown);
 	if (ret)
 		goto err_encoder_cleanup;
 
-- 
2.5.0

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

* [PATCH v2 4/9] drm: atmel-hlcdc: remove leftovers from atomic mode setting migration
  2016-03-16 13:57 [PATCH v2 0/9] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
                   ` (2 preceding siblings ...)
  2016-03-16 13:57 ` [PATCH v2 3/9] drm: atmel-hlcdc: fix connector and encoder types Boris Brezillon
@ 2016-03-16 13:57 ` Boris Brezillon
  2016-03-16 13:57 ` [PATCH v2 5/9] drm: atmel-hlcdc: support extended timing ranges on sama5d4 and sama5d2 Boris Brezillon
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Boris Brezillon @ 2016-03-16 13:57 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, dri-devel
  Cc: Nicolas Ferre, Jean-Christophe Plagniol-Villard,
	Alexandre Belloni, linux-arm-kernel, linux-kernel,
	Boris Brezillon

The ->dpms field is no longer used and can be removed.
The same goes for the dummy ->mode_fixup() implementation which always
returns true.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index 49494e9..2255dc9 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
@@ -44,13 +44,11 @@ enum atmel_hlcdc_connector_rgb_mode {
  * @connector: DRM connector
  * @encoder: DRM encoder
  * @dc: pointer to the atmel_hlcdc_dc structure
- * @dpms: current DPMS mode
  */
 struct atmel_hlcdc_rgb_output {
 	struct drm_connector connector;
 	struct drm_encoder encoder;
 	struct atmel_hlcdc_dc *dc;
-	int dpms;
 };
 
 static inline struct atmel_hlcdc_rgb_output *
@@ -104,14 +102,6 @@ static void atmel_hlcdc_panel_encoder_disable(struct drm_encoder *encoder)
 	drm_panel_disable(panel->panel);
 }
 
-static bool
-atmel_hlcdc_panel_encoder_mode_fixup(struct drm_encoder *encoder,
-				     const struct drm_display_mode *mode,
-				     struct drm_display_mode *adjusted)
-{
-	return true;
-}
-
 static void
 atmel_hlcdc_rgb_encoder_mode_set(struct drm_encoder *encoder,
 				 struct drm_display_mode *mode,
@@ -147,7 +137,6 @@ atmel_hlcdc_rgb_encoder_mode_set(struct drm_encoder *encoder,
 }
 
 static const struct drm_encoder_helper_funcs atmel_hlcdc_panel_encoder_helper_funcs = {
-	.mode_fixup = atmel_hlcdc_panel_encoder_mode_fixup,
 	.mode_set = atmel_hlcdc_rgb_encoder_mode_set,
 	.disable = atmel_hlcdc_panel_encoder_disable,
 	.enable = atmel_hlcdc_panel_encoder_enable,
@@ -248,7 +237,6 @@ static int atmel_hlcdc_create_panel_output(struct drm_device *dev,
 	if (!panel)
 		return -EINVAL;
 
-	panel->base.dpms = DRM_MODE_DPMS_OFF;
 
 	panel->base.dc = dc;
 
-- 
2.5.0

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

* [PATCH v2 5/9] drm: atmel-hlcdc: support extended timing ranges on sama5d4 and sama5d2
  2016-03-16 13:57 [PATCH v2 0/9] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
                   ` (3 preceding siblings ...)
  2016-03-16 13:57 ` [PATCH v2 4/9] drm: atmel-hlcdc: remove leftovers from atomic mode setting migration Boris Brezillon
@ 2016-03-16 13:57 ` Boris Brezillon
  2016-03-16 13:57 ` [PATCH v2 6/9] drm: atmel-hlcdc: move output mode selection in CRTC implementation Boris Brezillon
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Boris Brezillon @ 2016-03-16 13:57 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, dri-devel
  Cc: Nicolas Ferre, Jean-Christophe Plagniol-Villard,
	Alexandre Belloni, linux-arm-kernel, linux-kernel,
	Boris Brezillon

The display timings on old SoCs older than the sama5d4 are quite limited
and prevent the use of many displays. Add support for extended timing
ranges on sama5d2 and sama5d4.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 24 ++++++++++++++++++------
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h |  6 ++++++
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 851b4a0..70006a3 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -50,6 +50,9 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_at91sam9n12 = {
 	.min_height = 0,
 	.max_width = 1280,
 	.max_height = 860,
+	.max_spw = 0x3f,
+	.max_vpw = 0x3f,
+	.max_hpw = 0xff,
 	.nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9n12_layers),
 	.layers = atmel_hlcdc_at91sam9n12_layers,
 };
@@ -134,6 +137,9 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_at91sam9x5 = {
 	.min_height = 0,
 	.max_width = 800,
 	.max_height = 600,
+	.max_spw = 0x3f,
+	.max_vpw = 0x3f,
+	.max_hpw = 0xff,
 	.nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9x5_layers),
 	.layers = atmel_hlcdc_at91sam9x5_layers,
 };
@@ -237,6 +243,9 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sama5d3 = {
 	.min_height = 0,
 	.max_width = 2048,
 	.max_height = 2048,
+	.max_spw = 0x3f,
+	.max_vpw = 0x3f,
+	.max_hpw = 0x1ff,
 	.nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d3_layers),
 	.layers = atmel_hlcdc_sama5d3_layers,
 };
@@ -320,6 +329,9 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sama5d4 = {
 	.min_height = 0,
 	.max_width = 2048,
 	.max_height = 2048,
+	.max_spw = 0xff,
+	.max_vpw = 0xff,
+	.max_hpw = 0x3ff,
 	.nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d4_layers),
 	.layers = atmel_hlcdc_sama5d4_layers,
 };
@@ -358,19 +370,19 @@ int atmel_hlcdc_dc_mode_valid(struct atmel_hlcdc_dc *dc,
 	int hback_porch = mode->htotal - mode->hsync_end;
 	int hsync_len = mode->hsync_end - mode->hsync_start;
 
-	if (hsync_len > 0x40 || hsync_len < 1)
+	if (hsync_len > dc->desc->max_spw + 1 || hsync_len < 1)
 		return MODE_HSYNC;
 
-	if (vsync_len > 0x40 || vsync_len < 1)
+	if (vsync_len > dc->desc->max_spw + 1 || vsync_len < 1)
 		return MODE_VSYNC;
 
-	if (hfront_porch > 0x200 || hfront_porch < 1 ||
-	    hback_porch > 0x200 || hback_porch < 1 ||
+	if (hfront_porch > dc->desc->max_hpw + 1 || hfront_porch < 1 ||
+	    hback_porch > dc->desc->max_hpw + 1 || hback_porch < 1 ||
 	    mode->hdisplay < 1)
 		return MODE_H_ILLEGAL;
 
-	if (vfront_porch > 0x40 || vfront_porch < 1 ||
-	    vback_porch > 0x40 || vback_porch < 0 ||
+	if (vfront_porch > dc->desc->max_vpw + 1 || vfront_porch < 1 ||
+	    vback_porch > dc->desc->max_vpw || vback_porch < 0 ||
 	    mode->vdisplay < 1)
 		return MODE_V_ILLEGAL;
 
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
index 53b4488..23521ba 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
@@ -50,6 +50,9 @@
  * @min_height: minimum height supported by the Display Controller
  * @max_width: maximum width supported by the Display Controller
  * @max_height: maximum height supported by the Display Controller
+ * @max_spw: maximum vertical/horizontal pulse width
+ * @max_vpw: maximum vertical back/front porch width
+ * @max_hpw: maximum horizontal back/front porch width
  * @layers: a layer description table describing available layers
  * @nlayers: layer description table size
  */
@@ -58,6 +61,9 @@ struct atmel_hlcdc_dc_desc {
 	int min_height;
 	int max_width;
 	int max_height;
+	int max_spw;
+	int max_vpw;
+	int max_hpw;
 	const struct atmel_hlcdc_layer_desc *layers;
 	int nlayers;
 };
-- 
2.5.0

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

* [PATCH v2 6/9] drm: atmel-hlcdc: move output mode selection in CRTC implementation
  2016-03-16 13:57 [PATCH v2 0/9] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
                   ` (4 preceding siblings ...)
  2016-03-16 13:57 ` [PATCH v2 5/9] drm: atmel-hlcdc: support extended timing ranges on sama5d4 and sama5d2 Boris Brezillon
@ 2016-03-16 13:57 ` Boris Brezillon
  2016-03-16 13:57 ` [PATCH v2 7/9] drm: atmel-hlcdc: rework the output code to support drm bridges Boris Brezillon
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Boris Brezillon @ 2016-03-16 13:57 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, dri-devel
  Cc: Nicolas Ferre, Jean-Christophe Plagniol-Villard,
	Alexandre Belloni, linux-arm-kernel, linux-kernel,
	Boris Brezillon

In order to support multiple outputs we need to move the output mode
selection to the CRTC object, so that the output validity check can be
done against the drm_atomic_state.

If the connectors selected by a specific mode setting are requiring
incompatible bus format the atomic operation is aborted (->atomic_check()
returns -EINVAL).

In order to implement that, we need to define our own CRTC state and
overload default ->reset(), ->atomic_duplicate_state() and
->atomic_destroy_state() functions.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c   | 140 ++++++++++++++++++++++-
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c     |   3 +
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h     |   3 +
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c |  46 --------
 4 files changed, 142 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
index 9863291..12ec204 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -32,6 +32,23 @@
 #include "atmel_hlcdc_dc.h"
 
 /**
+ * Atmel HLCDC CRTC state structure
+ *
+ * @base: base CRTC state
+ * @output_mode: RGBXXX output mode
+ */
+struct atmel_hlcdc_crtc_state {
+	struct drm_crtc_state base;
+	unsigned int output_mode;
+};
+
+static inline struct atmel_hlcdc_crtc_state *
+drm_crtc_state_to_atmel_hlcdc_crtc_state(struct drm_crtc_state *state)
+{
+	return container_of(state, struct atmel_hlcdc_crtc_state, base);
+}
+
+/**
  * Atmel HLCDC CRTC structure
  *
  * @base: base DRM CRTC structure
@@ -59,6 +76,7 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
 	struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
 	struct regmap *regmap = crtc->dc->hlcdc->regmap;
 	struct drm_display_mode *adj = &c->state->adjusted_mode;
+	struct atmel_hlcdc_crtc_state *state;
 	unsigned long mode_rate;
 	struct videomode vm;
 	unsigned long prate;
@@ -112,12 +130,15 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
 	if (adj->flags & DRM_MODE_FLAG_NHSYNC)
 		cfg |= ATMEL_HLCDC_HSPOL;
 
+	state = drm_crtc_state_to_atmel_hlcdc_crtc_state(c->state);
+	cfg |= state->output_mode << 8;
+
 	regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5),
 			   ATMEL_HLCDC_HSPOL | ATMEL_HLCDC_VSPOL |
 			   ATMEL_HLCDC_VSPDLYS | ATMEL_HLCDC_VSPDLYE |
 			   ATMEL_HLCDC_DISPPOL | ATMEL_HLCDC_DISPDLY |
 			   ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO |
-			   ATMEL_HLCDC_GUARDTIME_MASK,
+			   ATMEL_HLCDC_GUARDTIME_MASK | ATMEL_HLCDC_MODE_MASK,
 			   cfg);
 }
 
@@ -228,14 +249,78 @@ void atmel_hlcdc_crtc_resume(struct drm_crtc *c)
 	}
 }
 
+#define ATMEL_HLCDC_RGB444_OUTPUT	BIT(0)
+#define ATMEL_HLCDC_RGB565_OUTPUT	BIT(1)
+#define ATMEL_HLCDC_RGB666_OUTPUT	BIT(2)
+#define ATMEL_HLCDC_RGB888_OUTPUT	BIT(3)
+#define ATMEL_HLCDC_OUTPUT_MODE_MASK	GENMASK(3, 0)
+
+static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state)
+{
+	unsigned int output_fmts = ATMEL_HLCDC_OUTPUT_MODE_MASK;
+	struct atmel_hlcdc_crtc_state *hstate;
+	struct drm_connector_state *cstate;
+	struct drm_connector *connector;
+	struct atmel_hlcdc_crtc *crtc;
+	int i;
+
+	crtc = drm_crtc_to_atmel_hlcdc_crtc(state->crtc);
+
+	for_each_connector_in_state(state->state, connector, cstate, i) {
+		struct drm_display_info *info = &connector->display_info;
+		unsigned int supported_fmts = 0;
+		int j;
+
+		if (!cstate->crtc)
+			continue;
+
+		for (j = 0; j < info->num_bus_formats; j++) {
+			switch (info->bus_formats[j]) {
+			case MEDIA_BUS_FMT_RGB444_1X12:
+				supported_fmts |= ATMEL_HLCDC_RGB444_OUTPUT;
+				break;
+			case MEDIA_BUS_FMT_RGB565_1X16:
+				supported_fmts |= ATMEL_HLCDC_RGB565_OUTPUT;
+				break;
+			case MEDIA_BUS_FMT_RGB666_1X18:
+				supported_fmts |= ATMEL_HLCDC_RGB666_OUTPUT;
+				break;
+			case MEDIA_BUS_FMT_RGB888_1X24:
+				supported_fmts |= ATMEL_HLCDC_RGB888_OUTPUT;
+				break;
+			default:
+				break;
+			}
+		}
+
+		if (crtc->dc->desc->conflicting_output_formats)
+			output_fmts &= supported_fmts;
+		else
+			output_fmts |= supported_fmts;
+	}
+
+	if (!output_fmts)
+		return -EINVAL;
+
+	hstate = drm_crtc_state_to_atmel_hlcdc_crtc_state(state);
+	hstate->output_mode = fls(output_fmts) - 1;
+
+	return 0;
+}
+
 static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c,
 					 struct drm_crtc_state *s)
 {
 	struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
+	int ret;
 
 	if (atmel_hlcdc_dc_mode_valid(crtc->dc, &s->adjusted_mode) != MODE_OK)
 		return -EINVAL;
 
+	ret = atmel_hlcdc_crtc_select_output_mode(s);
+	if (ret)
+		return ret;
+
 	return atmel_hlcdc_plane_prepare_disc_area(s);
 }
 
@@ -300,13 +385,60 @@ void atmel_hlcdc_crtc_irq(struct drm_crtc *c)
 	atmel_hlcdc_crtc_finish_page_flip(drm_crtc_to_atmel_hlcdc_crtc(c));
 }
 
+void atmel_hlcdc_crtc_reset(struct drm_crtc *crtc)
+{
+	struct atmel_hlcdc_crtc_state *state;
+
+	if (crtc->state && crtc->state->mode_blob)
+		drm_property_unreference_blob(crtc->state->mode_blob);
+
+	if (crtc->state) {
+		state = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
+		kfree(state);
+	}
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (state) {
+		crtc->state = &state->base;
+		crtc->state->crtc = crtc;
+	}
+}
+
+static struct drm_crtc_state *
+atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+	struct atmel_hlcdc_crtc_state *state, *cur;
+
+	if (WARN_ON(!crtc->state))
+		return NULL;
+
+	state = kmalloc(sizeof(*state), GFP_KERNEL);
+	if (state)
+		__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
+
+	cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
+	state->output_mode = cur->output_mode;
+
+	return &state->base;
+}
+
+static void atmel_hlcdc_crtc_destroy_state(struct drm_crtc *crtc,
+					   struct drm_crtc_state *s)
+{
+	struct atmel_hlcdc_crtc_state *state;
+
+	state = drm_crtc_state_to_atmel_hlcdc_crtc_state(s);
+	__drm_atomic_helper_crtc_destroy_state(crtc, s);
+	kfree(state);
+}
+
 static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
 	.page_flip = drm_atomic_helper_page_flip,
 	.set_config = drm_atomic_helper_set_config,
 	.destroy = atmel_hlcdc_crtc_destroy,
-	.reset = drm_atomic_helper_crtc_reset,
-	.atomic_duplicate_state =  drm_atomic_helper_crtc_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+	.reset = atmel_hlcdc_crtc_reset,
+	.atomic_duplicate_state =  atmel_hlcdc_crtc_duplicate_state,
+	.atomic_destroy_state = atmel_hlcdc_crtc_destroy_state,
 };
 
 int atmel_hlcdc_crtc_create(struct drm_device *dev)
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 70006a3..930d603 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -53,6 +53,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_at91sam9n12 = {
 	.max_spw = 0x3f,
 	.max_vpw = 0x3f,
 	.max_hpw = 0xff,
+	.conflicting_output_formats = true,
 	.nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9n12_layers),
 	.layers = atmel_hlcdc_at91sam9n12_layers,
 };
@@ -140,6 +141,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_at91sam9x5 = {
 	.max_spw = 0x3f,
 	.max_vpw = 0x3f,
 	.max_hpw = 0xff,
+	.conflicting_output_formats = true,
 	.nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9x5_layers),
 	.layers = atmel_hlcdc_at91sam9x5_layers,
 };
@@ -246,6 +248,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sama5d3 = {
 	.max_spw = 0x3f,
 	.max_vpw = 0x3f,
 	.max_hpw = 0x1ff,
+	.conflicting_output_formats = true,
 	.nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d3_layers),
 	.layers = atmel_hlcdc_sama5d3_layers,
 };
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
index 23521ba..302c958 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
@@ -53,6 +53,8 @@
  * @max_spw: maximum vertical/horizontal pulse width
  * @max_vpw: maximum vertical back/front porch width
  * @max_hpw: maximum horizontal back/front porch width
+ * @conflicting_output_formats: true if RGBXXX output formats conflict with
+ *				each other.
  * @layers: a layer description table describing available layers
  * @nlayers: layer description table size
  */
@@ -64,6 +66,7 @@ struct atmel_hlcdc_dc_desc {
 	int max_spw;
 	int max_vpw;
 	int max_hpw;
+	bool conflicting_output_formats;
 	const struct atmel_hlcdc_layer_desc *layers;
 	int nlayers;
 };
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index 2255dc9..75237b5 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
@@ -27,16 +27,6 @@
 #include "atmel_hlcdc_dc.h"
 
 /**
- * Atmel HLCDC RGB output mode
- */
-enum atmel_hlcdc_connector_rgb_mode {
-	ATMEL_HLCDC_CONNECTOR_RGB444,
-	ATMEL_HLCDC_CONNECTOR_RGB565,
-	ATMEL_HLCDC_CONNECTOR_RGB666,
-	ATMEL_HLCDC_CONNECTOR_RGB888,
-};
-
-/**
  * Atmel HLCDC RGB connector structure
  *
  * This structure stores RGB slave device information.
@@ -89,7 +79,6 @@ static void atmel_hlcdc_panel_encoder_enable(struct drm_encoder *encoder)
 	struct atmel_hlcdc_rgb_output *rgb =
 			drm_encoder_to_atmel_hlcdc_rgb_output(encoder);
 	struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb);
-
 	drm_panel_enable(panel->panel);
 }
 
@@ -102,42 +91,7 @@ static void atmel_hlcdc_panel_encoder_disable(struct drm_encoder *encoder)
 	drm_panel_disable(panel->panel);
 }
 
-static void
-atmel_hlcdc_rgb_encoder_mode_set(struct drm_encoder *encoder,
-				 struct drm_display_mode *mode,
-				 struct drm_display_mode *adjusted)
-{
-	struct atmel_hlcdc_rgb_output *rgb =
-			drm_encoder_to_atmel_hlcdc_rgb_output(encoder);
-	struct drm_display_info *info = &rgb->connector.display_info;
-	unsigned int cfg;
-
-	cfg = 0;
-
-	if (info->num_bus_formats) {
-		switch (info->bus_formats[0]) {
-		case MEDIA_BUS_FMT_RGB565_1X16:
-			cfg |= ATMEL_HLCDC_CONNECTOR_RGB565 << 8;
-			break;
-		case MEDIA_BUS_FMT_RGB666_1X18:
-			cfg |= ATMEL_HLCDC_CONNECTOR_RGB666 << 8;
-			break;
-		case MEDIA_BUS_FMT_RGB888_1X24:
-			cfg |= ATMEL_HLCDC_CONNECTOR_RGB888 << 8;
-			break;
-		case MEDIA_BUS_FMT_RGB444_1X12:
-		default:
-			break;
-		}
-	}
-
-	regmap_update_bits(rgb->dc->hlcdc->regmap, ATMEL_HLCDC_CFG(5),
-			   ATMEL_HLCDC_MODE_MASK,
-			   cfg);
-}
-
 static const struct drm_encoder_helper_funcs atmel_hlcdc_panel_encoder_helper_funcs = {
-	.mode_set = atmel_hlcdc_rgb_encoder_mode_set,
 	.disable = atmel_hlcdc_panel_encoder_disable,
 	.enable = atmel_hlcdc_panel_encoder_enable,
 };
-- 
2.5.0

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

* [PATCH v2 7/9] drm: atmel-hlcdc: rework the output code to support drm bridges
  2016-03-16 13:57 [PATCH v2 0/9] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
                   ` (5 preceding siblings ...)
  2016-03-16 13:57 ` [PATCH v2 6/9] drm: atmel-hlcdc: move output mode selection in CRTC implementation Boris Brezillon
@ 2016-03-16 13:57 ` Boris Brezillon
  2016-03-16 13:57 ` [PATCH v2 8/9] drm: atmel-hlcdc: check display mode validity in crtc->mode_fixup() Boris Brezillon
  2016-03-16 13:57 ` [PATCH v2 9/9] drm: atmel-hlcdc: route DMA accesses through AHB interfaces Boris Brezillon
  8 siblings, 0 replies; 15+ messages in thread
From: Boris Brezillon @ 2016-03-16 13:57 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, dri-devel
  Cc: Nicolas Ferre, Jean-Christophe Plagniol-Villard,
	Alexandre Belloni, linux-arm-kernel, linux-kernel,
	Boris Brezillon

The current output code only supports connection to drm panels.
First simplify the drm panel code, and then add support for external drm
bridges.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c     |   2 +-
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 193 +++++++++++++----------
 2 files changed, 113 insertions(+), 82 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 930d603..b33f19d 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -551,7 +551,7 @@ static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev)
 
 	ret = atmel_hlcdc_create_outputs(dev);
 	if (ret) {
-		dev_err(dev->dev, "failed to create panel: %d\n", ret);
+		dev_err(dev->dev, "failed to create HLCDC outputs: %d\n", ret);
 		return ret;
 	}
 
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index 75237b5..39802c0 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
@@ -34,11 +34,13 @@
  * @connector: DRM connector
  * @encoder: DRM encoder
  * @dc: pointer to the atmel_hlcdc_dc structure
+ * @panel: panel connected on the RGB output
  */
 struct atmel_hlcdc_rgb_output {
 	struct drm_connector connector;
 	struct drm_encoder encoder;
 	struct atmel_hlcdc_dc *dc;
+	struct drm_panel *panel;
 };
 
 static inline struct atmel_hlcdc_rgb_output *
@@ -54,46 +56,31 @@ drm_encoder_to_atmel_hlcdc_rgb_output(struct drm_encoder *encoder)
 	return container_of(encoder, struct atmel_hlcdc_rgb_output, encoder);
 }
 
-/**
- * Atmel HLCDC Panel device structure
- *
- * This structure is specialization of the slave device structure to
- * interface with drm panels.
- *
- * @base: base slave device fields
- * @panel: drm panel attached to this slave device
- */
-struct atmel_hlcdc_panel {
-	struct atmel_hlcdc_rgb_output base;
-	struct drm_panel *panel;
-};
-
-static inline struct atmel_hlcdc_panel *
-atmel_hlcdc_rgb_output_to_panel(struct atmel_hlcdc_rgb_output *output)
-{
-	return container_of(output, struct atmel_hlcdc_panel, base);
-}
-
-static void atmel_hlcdc_panel_encoder_enable(struct drm_encoder *encoder)
+static void atmel_hlcdc_rgb_encoder_enable(struct drm_encoder *encoder)
 {
 	struct atmel_hlcdc_rgb_output *rgb =
 			drm_encoder_to_atmel_hlcdc_rgb_output(encoder);
-	struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb);
-	drm_panel_enable(panel->panel);
+
+	if (rgb->panel) {
+		drm_panel_prepare(rgb->panel);
+		drm_panel_enable(rgb->panel);
+	}
 }
 
-static void atmel_hlcdc_panel_encoder_disable(struct drm_encoder *encoder)
+static void atmel_hlcdc_rgb_encoder_disable(struct drm_encoder *encoder)
 {
 	struct atmel_hlcdc_rgb_output *rgb =
 			drm_encoder_to_atmel_hlcdc_rgb_output(encoder);
-	struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb);
 
-	drm_panel_disable(panel->panel);
+	if (rgb->panel) {
+		drm_panel_disable(rgb->panel);
+		drm_panel_unprepare(rgb->panel);
+	}
 }
 
 static const struct drm_encoder_helper_funcs atmel_hlcdc_panel_encoder_helper_funcs = {
-	.disable = atmel_hlcdc_panel_encoder_disable,
-	.enable = atmel_hlcdc_panel_encoder_enable,
+	.disable = atmel_hlcdc_rgb_encoder_disable,
+	.enable = atmel_hlcdc_rgb_encoder_enable,
 };
 
 static void atmel_hlcdc_rgb_encoder_destroy(struct drm_encoder *encoder)
@@ -110,9 +97,11 @@ static int atmel_hlcdc_panel_get_modes(struct drm_connector *connector)
 {
 	struct atmel_hlcdc_rgb_output *rgb =
 			drm_connector_to_atmel_hlcdc_rgb_output(connector);
-	struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb);
 
-	return panel->panel->funcs->get_modes(panel->panel);
+	if (rgb->panel)
+		return rgb->panel->funcs->get_modes(rgb->panel);
+
+	return 0;
 }
 
 static int atmel_hlcdc_rgb_mode_valid(struct drm_connector *connector,
@@ -144,7 +133,13 @@ static const struct drm_connector_helper_funcs atmel_hlcdc_panel_connector_helpe
 static enum drm_connector_status
 atmel_hlcdc_panel_connector_detect(struct drm_connector *connector, bool force)
 {
-	return connector_status_connected;
+	struct atmel_hlcdc_rgb_output *rgb =
+			drm_connector_to_atmel_hlcdc_rgb_output(connector);
+
+	if (rgb->panel)
+		return connector_status_connected;
+
+	return connector_status_disconnected;
 }
 
 static void
@@ -152,9 +147,10 @@ atmel_hlcdc_panel_connector_destroy(struct drm_connector *connector)
 {
 	struct atmel_hlcdc_rgb_output *rgb =
 			drm_connector_to_atmel_hlcdc_rgb_output(connector);
-	struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb);
 
-	drm_panel_detach(panel->panel);
+	if (rgb->panel)
+		drm_panel_detach(rgb->panel);
+
 	drm_connector_cleanup(connector);
 }
 
@@ -168,87 +164,122 @@ static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = {
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int atmel_hlcdc_create_panel_output(struct drm_device *dev,
-					   struct of_endpoint *ep)
+static int atmel_hlcdc_check_endpoint(struct drm_device *dev,
+				      const struct of_endpoint *ep)
 {
-	struct atmel_hlcdc_dc *dc = dev->dev_private;
 	struct device_node *np;
-	struct drm_panel *p = NULL;
-	struct atmel_hlcdc_panel *panel;
-	int ret;
+	void *obj;
 
 	np = of_graph_get_remote_port_parent(ep->local_node);
-	if (!np)
-		return -EINVAL;
 
-	p = of_drm_find_panel(np);
+	obj = of_drm_find_panel(np);
+	if (!obj)
+		obj = of_drm_find_bridge(np);
+
 	of_node_put(np);
 
-	if (!p)
-		return -EPROBE_DEFER;
+	return obj ? 0 : -EPROBE_DEFER;
+}
 
-	panel = devm_kzalloc(dev->dev, sizeof(*panel), GFP_KERNEL);
-	if (!panel)
-		return -EINVAL;
+static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
+				       const struct of_endpoint *ep)
+{
+	struct atmel_hlcdc_dc *dc = dev->dev_private;
+	struct atmel_hlcdc_rgb_output *output;
+	struct device_node *np;
+	struct drm_panel *panel;
+	struct drm_bridge *bridge;
+	int ret;
 
+	output = devm_kzalloc(dev->dev, sizeof(*output), GFP_KERNEL);
+	if (!output)
+		return -EINVAL;
 
-	panel->base.dc = dc;
+	output->dc = dc;
 
-	drm_encoder_helper_add(&panel->base.encoder,
+	drm_encoder_helper_add(&output->encoder,
 			       &atmel_hlcdc_panel_encoder_helper_funcs);
-	ret = drm_encoder_init(dev, &panel->base.encoder,
+	ret = drm_encoder_init(dev, &output->encoder,
 			       &atmel_hlcdc_panel_encoder_funcs,
 			       DRM_MODE_ENCODER_NONE, NULL);
 	if (ret)
 		return ret;
 
-	panel->base.connector.dpms = DRM_MODE_DPMS_OFF;
-	panel->base.connector.polled = DRM_CONNECTOR_POLL_CONNECT;
-	drm_connector_helper_add(&panel->base.connector,
-				 &atmel_hlcdc_panel_connector_helper_funcs);
-	ret = drm_connector_init(dev, &panel->base.connector,
-				 &atmel_hlcdc_panel_connector_funcs,
-				 DRM_MODE_CONNECTOR_Unknown);
-	if (ret)
-		goto err_encoder_cleanup;
+	output->encoder.possible_crtcs = 0x1;
+
+	np = of_graph_get_remote_port_parent(ep->local_node);
 
-	drm_mode_connector_attach_encoder(&panel->base.connector,
-					  &panel->base.encoder);
-	panel->base.encoder.possible_crtcs = 0x1;
+	ret = -EPROBE_DEFER;
 
-	drm_panel_attach(p, &panel->base.connector);
-	panel->panel = p;
+	panel = of_drm_find_panel(np);
+	if (panel) {
+		of_node_put(np);
+		output->connector.dpms = DRM_MODE_DPMS_OFF;
+		output->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
+		drm_connector_helper_add(&output->connector,
+				&atmel_hlcdc_panel_connector_helper_funcs);
+		ret = drm_connector_init(dev, &output->connector,
+					 &atmel_hlcdc_panel_connector_funcs,
+					 DRM_MODE_CONNECTOR_Unknown);
+		if (ret)
+			goto err_encoder_cleanup;
 
-	return 0;
+		drm_mode_connector_attach_encoder(&output->connector,
+						  &output->encoder);
+
+		ret = drm_panel_attach(panel, &output->connector);
+		if (ret) {
+			drm_connector_cleanup(&output->connector);
+			goto err_encoder_cleanup;
+		}
+
+		output->panel = panel;
+
+		return 0;
+	}
+
+	bridge = of_drm_find_bridge(np);
+	of_node_put(np);
+
+	if (bridge) {
+		output->encoder.bridge = bridge;
+		bridge->encoder = &output->encoder;
+		ret = drm_bridge_attach(dev, bridge);
+		if (!ret)
+			return 0;
+	}
 
 err_encoder_cleanup:
-	drm_encoder_cleanup(&panel->base.encoder);
+	drm_encoder_cleanup(&output->encoder);
 
 	return ret;
 }
 
 int atmel_hlcdc_create_outputs(struct drm_device *dev)
 {
-	struct device_node *port_np, *np;
+	struct device_node *ep_np = NULL;
 	struct of_endpoint ep;
 	int ret;
 
-	port_np = of_get_child_by_name(dev->dev->of_node, "port");
-	if (!port_np)
-		return -EINVAL;
+	for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
+		ret = of_graph_parse_endpoint(ep_np, &ep);
+		if (!ret)
+			ret = atmel_hlcdc_check_endpoint(dev, &ep);
 
-	np = of_get_child_by_name(port_np, "endpoint");
-	of_node_put(port_np);
+		of_node_put(ep_np);
+		if (ret)
+			return ret;
+	}
 
-	if (!np)
-		return -EINVAL;
+	for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
+		ret = of_graph_parse_endpoint(ep_np, &ep);
+		if (!ret)
+			ret = atmel_hlcdc_attach_endpoint(dev, &ep);
 
-	ret = of_graph_parse_endpoint(np, &ep);
-	of_node_put(port_np);
+		of_node_put(ep_np);
+		if (ret)
+			return ret;
+	}
 
-	if (ret)
-		return ret;
-
-	/* We currently only support panel output */
-	return atmel_hlcdc_create_panel_output(dev, &ep);
+	return 0;
 }
-- 
2.5.0

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

* [PATCH v2 8/9] drm: atmel-hlcdc: check display mode validity in crtc->mode_fixup()
  2016-03-16 13:57 [PATCH v2 0/9] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
                   ` (6 preceding siblings ...)
  2016-03-16 13:57 ` [PATCH v2 7/9] drm: atmel-hlcdc: rework the output code to support drm bridges Boris Brezillon
@ 2016-03-16 13:57 ` Boris Brezillon
  2016-03-16 13:57 ` [PATCH v2 9/9] drm: atmel-hlcdc: route DMA accesses through AHB interfaces Boris Brezillon
  8 siblings, 0 replies; 15+ messages in thread
From: Boris Brezillon @ 2016-03-16 13:57 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, dri-devel
  Cc: Nicolas Ferre, Jean-Christophe Plagniol-Villard,
	Alexandre Belloni, linux-arm-kernel, linux-kernel,
	Boris Brezillon

Move the adjusted display mode check into ->mode_fixup().

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
index 12ec204..cbba029 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -142,11 +142,13 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
 			   cfg);
 }
 
-static bool atmel_hlcdc_crtc_mode_fixup(struct drm_crtc *crtc,
+static bool atmel_hlcdc_crtc_mode_fixup(struct drm_crtc *c,
 					const struct drm_display_mode *mode,
 					struct drm_display_mode *adjusted_mode)
 {
-	return true;
+	struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
+
+	return atmel_hlcdc_dc_mode_valid(crtc->dc, adjusted_mode) == MODE_OK;
 }
 
 static void atmel_hlcdc_crtc_disable(struct drm_crtc *c)
@@ -311,12 +313,8 @@ static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state)
 static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c,
 					 struct drm_crtc_state *s)
 {
-	struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
 	int ret;
 
-	if (atmel_hlcdc_dc_mode_valid(crtc->dc, &s->adjusted_mode) != MODE_OK)
-		return -EINVAL;
-
 	ret = atmel_hlcdc_crtc_select_output_mode(s);
 	if (ret)
 		return ret;
-- 
2.5.0

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

* [PATCH v2 9/9] drm: atmel-hlcdc: route DMA accesses through AHB interfaces
  2016-03-16 13:57 [PATCH v2 0/9] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
                   ` (7 preceding siblings ...)
  2016-03-16 13:57 ` [PATCH v2 8/9] drm: atmel-hlcdc: check display mode validity in crtc->mode_fixup() Boris Brezillon
@ 2016-03-16 13:57 ` Boris Brezillon
  8 siblings, 0 replies; 15+ messages in thread
From: Boris Brezillon @ 2016-03-16 13:57 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, dri-devel
  Cc: Nicolas Ferre, Jean-Christophe Plagniol-Villard,
	Alexandre Belloni, linux-arm-kernel, linux-kernel,
	Boris Brezillon

In relation with the actuall bandwidth consumed on a DMA Source interface,
choose the less used one for a created plane.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c  |  6 +++-
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h    |  1 +
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 43 +++++++++++++++++++++++--
 3 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
index cbba029..14e74e5 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -319,7 +319,11 @@ static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c,
 	if (ret)
 		return ret;
 
-	return atmel_hlcdc_plane_prepare_disc_area(s);
+	ret = atmel_hlcdc_plane_prepare_disc_area(s);
+	if (ret)
+		return ret;
+
+	return atmel_hlcdc_plane_prepare_ahb_routing(s);
 }
 
 static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c,
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
index 302c958..c71a300 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
@@ -165,6 +165,7 @@ struct atmel_hlcdc_planes *
 atmel_hlcdc_create_planes(struct drm_device *dev);
 
 int atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state);
+int atmel_hlcdc_plane_prepare_ahb_routing(struct drm_crtc_state *c_state);
 
 void atmel_hlcdc_crtc_irq(struct drm_crtc *c);
 
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index 35027d0..0995eef 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -58,6 +58,8 @@ struct atmel_hlcdc_plane_state {
 	int disc_w;
 	int disc_h;
 
+	int ahb_id;
+
 	/* These fields are private and should not be touched */
 	int bpp[ATMEL_HLCDC_MAX_PLANES];
 	unsigned int offsets[ATMEL_HLCDC_MAX_PLANES];
@@ -359,8 +361,10 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
 
 	atmel_hlcdc_layer_update_cfg(&plane->layer,
 				     ATMEL_HLCDC_LAYER_DMA_CFG_ID,
-				     ATMEL_HLCDC_LAYER_DMA_BLEN_MASK,
-				     ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16);
+				     ATMEL_HLCDC_LAYER_DMA_BLEN_MASK |
+				     ATMEL_HLCDC_LAYER_DMA_SIF,
+				     ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 |
+				     state->ahb_id);
 
 	atmel_hlcdc_layer_update_cfg(&plane->layer, layout->general_config,
 				     ATMEL_HLCDC_LAYER_ITER2BL |
@@ -435,6 +439,41 @@ static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane,
 	}
 }
 
+int atmel_hlcdc_plane_prepare_ahb_routing(struct drm_crtc_state *c_state)
+{
+	unsigned int ahb_load[2] = { };
+	struct drm_plane *plane;
+
+	drm_atomic_crtc_state_for_each_plane(plane, c_state) {
+		struct atmel_hlcdc_plane_state *plane_state;
+		struct drm_plane_state *plane_s;
+		unsigned int pixels, load = 0;
+		int i;
+
+		plane_s = drm_atomic_get_plane_state(c_state->state, plane);
+		if (IS_ERR(plane_s))
+			return PTR_ERR(plane_s);
+
+		plane_state =
+			drm_plane_state_to_atmel_hlcdc_plane_state(plane_s);
+
+		pixels = (plane_state->src_w * plane_state->src_h) -
+			 (plane_state->disc_w * plane_state->disc_h);
+
+		for (i = 0; i < plane_state->nplanes; i++)
+			load += pixels * plane_state->bpp[i];
+
+		if (ahb_load[0] <= ahb_load[1])
+			plane_state->ahb_id = 0;
+		else
+			plane_state->ahb_id = 1;
+
+		ahb_load[plane_state->ahb_id] += load;
+	}
+
+	return 0;
+}
+
 int
 atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state)
 {
-- 
2.5.0

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

* Re: [PATCH v2 1/9] drm: atmel-hlcdc: add a ->cleanup_fb() operation
  2016-03-16 13:57 ` [PATCH v2 1/9] drm: atmel-hlcdc: add a ->cleanup_fb() operation Boris Brezillon
@ 2016-03-16 15:17   ` Daniel Vetter
  2016-03-17  8:49     ` Boris Brezillon
  0 siblings, 1 reply; 15+ messages in thread
From: Daniel Vetter @ 2016-03-16 15:17 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: David Airlie, Daniel Vetter, dri-devel, Nicolas Ferre,
	Jean-Christophe Plagniol-Villard, Alexandre Belloni,
	linux-arm-kernel, linux-kernel

On Wed, Mar 16, 2016 at 02:57:35PM +0100, Boris Brezillon wrote:
> Add a ->cleanup_fb() operation to avoid memory leaks when the atomic
> operation is interrupted after the ->prepare_fb() call.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> Fixes 2389fc1 ("drm: atmel-hlcdc: Atomic mode-setting conversion")
> Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h    |  2 ++
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 22 +++++++++++++++++++---
>  2 files changed, 21 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> index fed517f..ec64140 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> @@ -81,11 +81,13 @@ struct atmel_hlcdc_plane_properties {
>   * @layer: HLCDC layer structure
>   * @properties: pointer to the property definitions structure
>   * @rotation: current rotation status
> + * @prepared: flagging the plane has prepared for an atomic update
>   */
>  struct atmel_hlcdc_plane {
>  	struct drm_plane base;
>  	struct atmel_hlcdc_layer layer;
>  	struct atmel_hlcdc_plane_properties *properties;
> +	bool prepared;
>  };
>  
>  static inline struct atmel_hlcdc_plane *
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> index 1ffe9c3..35027d0 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> @@ -715,11 +715,25 @@ static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
>  					const struct drm_plane_state *new_state)
>  {
>  	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
> +	int ret;
>  
> -	if (!new_state->fb)
> -		return 0;
> +	ret = atmel_hlcdc_layer_update_start(&plane->layer);
> +	if (!ret)
> +		plane->prepared = true;

Atomic helpers will keep track of this for you, and only call ->cleanup_fb
on a plane combo where it did (successfully) call ->prepare_fb.
-Daniel

> +
> +	return ret;
> +}
> +
> +static void atmel_hlcdc_plane_cleanup_fb(struct drm_plane *p,
> +				const struct drm_plane_state *old_state)
> +{
> +	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
> +
> +	if (!plane->prepared)
> +		return;
>  
> -	return atmel_hlcdc_layer_update_start(&plane->layer);
> +	atmel_hlcdc_layer_update_rollback(&plane->layer);
> +	plane->prepared = false;
>  }
>  
>  static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
> @@ -739,6 +753,7 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
>  	atmel_hlcdc_plane_update_disc_area(plane, state);
>  
>  	atmel_hlcdc_layer_update_commit(&plane->layer);
> +	plane->prepared = false;
>  }
>  
>  static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p,
> @@ -844,6 +859,7 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
>  
>  static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
>  	.prepare_fb = atmel_hlcdc_plane_prepare_fb,
> +	.cleanup_fb = atmel_hlcdc_plane_cleanup_fb,
>  	.atomic_check = atmel_hlcdc_plane_atomic_check,
>  	.atomic_update = atmel_hlcdc_plane_atomic_update,
>  	.atomic_disable = atmel_hlcdc_plane_atomic_disable,
> -- 
> 2.5.0
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH v2 1/9] drm: atmel-hlcdc: add a ->cleanup_fb() operation
  2016-03-16 15:17   ` Daniel Vetter
@ 2016-03-17  8:49     ` Boris Brezillon
  2016-03-18 17:58       ` Daniel Vetter
  0 siblings, 1 reply; 15+ messages in thread
From: Boris Brezillon @ 2016-03-17  8:49 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: David Airlie, dri-devel, Nicolas Ferre,
	Jean-Christophe Plagniol-Villard, Alexandre Belloni,
	linux-arm-kernel, linux-kernel

Hi Daniel,

On Wed, 16 Mar 2016 16:17:38 +0100
Daniel Vetter <daniel@ffwll.ch> wrote:

> On Wed, Mar 16, 2016 at 02:57:35PM +0100, Boris Brezillon wrote:
> > Add a ->cleanup_fb() operation to avoid memory leaks when the atomic
> > operation is interrupted after the ->prepare_fb() call.
> > 
> > Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> > Fixes 2389fc1 ("drm: atmel-hlcdc: Atomic mode-setting conversion")
> > Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> > Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> > ---
> >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h    |  2 ++
> >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 22 +++++++++++++++++++---
> >  2 files changed, 21 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> > index fed517f..ec64140 100644
> > --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> > +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> > @@ -81,11 +81,13 @@ struct atmel_hlcdc_plane_properties {
> >   * @layer: HLCDC layer structure
> >   * @properties: pointer to the property definitions structure
> >   * @rotation: current rotation status
> > + * @prepared: flagging the plane has prepared for an atomic update
> >   */
> >  struct atmel_hlcdc_plane {
> >  	struct drm_plane base;
> >  	struct atmel_hlcdc_layer layer;
> >  	struct atmel_hlcdc_plane_properties *properties;
> > +	bool prepared;
> >  };
> >  
> >  static inline struct atmel_hlcdc_plane *
> > diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> > index 1ffe9c3..35027d0 100644
> > --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> > +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> > @@ -715,11 +715,25 @@ static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
> >  					const struct drm_plane_state *new_state)
> >  {
> >  	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
> > +	int ret;
> >  
> > -	if (!new_state->fb)
> > -		return 0;
> > +	ret = atmel_hlcdc_layer_update_start(&plane->layer);
> > +	if (!ret)
> > +		plane->prepared = true;
> 
> Atomic helpers will keep track of this for you, and only call ->cleanup_fb
> on a plane combo where it did (successfully) call ->prepare_fb.

Hm, it's not exactly encoding the same thing. What I want to do here is
call atmel_hlcdc_layer_update_rollback() only if the atomic update has
failed (see below, I set ->prepared back to false in the
->atomic_update() method). AFAICT, ->cleanup_fb() is also called
when the whole operation succeed (and in this case I don't want to
call atmel_hlcdc_layer_update_rollback()).

Let me know if you see a better approach to do that.

Thanks,

Boris

> -Daniel
> 
> > +
> > +	return ret;
> > +}
> > +
> > +static void atmel_hlcdc_plane_cleanup_fb(struct drm_plane *p,
> > +				const struct drm_plane_state *old_state)
> > +{
> > +	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
> > +
> > +	if (!plane->prepared)
> > +		return;
> >  
> > -	return atmel_hlcdc_layer_update_start(&plane->layer);
> > +	atmel_hlcdc_layer_update_rollback(&plane->layer);
> > +	plane->prepared = false;
> >  }
> >  
> >  static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
> > @@ -739,6 +753,7 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
> >  	atmel_hlcdc_plane_update_disc_area(plane, state);
> >  
> >  	atmel_hlcdc_layer_update_commit(&plane->layer);
> > +	plane->prepared = false;
> >  }
> >  
> >  static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p,
> > @@ -844,6 +859,7 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
> >  
> >  static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
> >  	.prepare_fb = atmel_hlcdc_plane_prepare_fb,
> > +	.cleanup_fb = atmel_hlcdc_plane_cleanup_fb,
> >  	.atomic_check = atmel_hlcdc_plane_atomic_check,
> >  	.atomic_update = atmel_hlcdc_plane_atomic_update,
> >  	.atomic_disable = atmel_hlcdc_plane_atomic_disable,
> > -- 
> > 2.5.0
> > 
> 



-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

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

* Re: [PATCH v2 1/9] drm: atmel-hlcdc: add a ->cleanup_fb() operation
  2016-03-17  8:49     ` Boris Brezillon
@ 2016-03-18 17:58       ` Daniel Vetter
  2016-03-19 10:48         ` Boris Brezillon
  2016-03-30 12:43         ` Boris Brezillon
  0 siblings, 2 replies; 15+ messages in thread
From: Daniel Vetter @ 2016-03-18 17:58 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Daniel Vetter, David Airlie, dri-devel, Nicolas Ferre,
	Jean-Christophe Plagniol-Villard, Alexandre Belloni,
	linux-arm-kernel, linux-kernel

On Thu, Mar 17, 2016 at 09:49:42AM +0100, Boris Brezillon wrote:
> Hi Daniel,
> 
> On Wed, 16 Mar 2016 16:17:38 +0100
> Daniel Vetter <daniel@ffwll.ch> wrote:
> 
> > On Wed, Mar 16, 2016 at 02:57:35PM +0100, Boris Brezillon wrote:
> > > Add a ->cleanup_fb() operation to avoid memory leaks when the atomic
> > > operation is interrupted after the ->prepare_fb() call.
> > > 
> > > Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> > > Fixes 2389fc1 ("drm: atmel-hlcdc: Atomic mode-setting conversion")
> > > Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> > > Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> > > ---
> > >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h    |  2 ++
> > >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 22 +++++++++++++++++++---
> > >  2 files changed, 21 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> > > index fed517f..ec64140 100644
> > > --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> > > +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> > > @@ -81,11 +81,13 @@ struct atmel_hlcdc_plane_properties {
> > >   * @layer: HLCDC layer structure
> > >   * @properties: pointer to the property definitions structure
> > >   * @rotation: current rotation status
> > > + * @prepared: flagging the plane has prepared for an atomic update
> > >   */
> > >  struct atmel_hlcdc_plane {
> > >  	struct drm_plane base;
> > >  	struct atmel_hlcdc_layer layer;
> > >  	struct atmel_hlcdc_plane_properties *properties;
> > > +	bool prepared;
> > >  };
> > >  
> > >  static inline struct atmel_hlcdc_plane *
> > > diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> > > index 1ffe9c3..35027d0 100644
> > > --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> > > +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> > > @@ -715,11 +715,25 @@ static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
> > >  					const struct drm_plane_state *new_state)
> > >  {
> > >  	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
> > > +	int ret;
> > >  
> > > -	if (!new_state->fb)
> > > -		return 0;
> > > +	ret = atmel_hlcdc_layer_update_start(&plane->layer);
> > > +	if (!ret)
> > > +		plane->prepared = true;
> > 
> > Atomic helpers will keep track of this for you, and only call ->cleanup_fb
> > on a plane combo where it did (successfully) call ->prepare_fb.
> 
> Hm, it's not exactly encoding the same thing. What I want to do here is
> call atmel_hlcdc_layer_update_rollback() only if the atomic update has
> failed (see below, I set ->prepared back to false in the
> ->atomic_update() method). AFAICT, ->cleanup_fb() is also called
> when the whole operation succeed (and in this case I don't want to
> call atmel_hlcdc_layer_update_rollback()).
> 
> Let me know if you see a better approach to do that.

Ah makes sense. And yeah I guess this is the only approach really. Note
that you should put plane_prepared into plane_state though, in case we
start to pipeline updates.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH v2 1/9] drm: atmel-hlcdc: add a ->cleanup_fb() operation
  2016-03-18 17:58       ` Daniel Vetter
@ 2016-03-19 10:48         ` Boris Brezillon
  2016-03-30 12:43         ` Boris Brezillon
  1 sibling, 0 replies; 15+ messages in thread
From: Boris Brezillon @ 2016-03-19 10:48 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: David Airlie, dri-devel, Nicolas Ferre,
	Jean-Christophe Plagniol-Villard, Alexandre Belloni,
	linux-arm-kernel, linux-kernel

On Fri, 18 Mar 2016 18:58:48 +0100
Daniel Vetter <daniel@ffwll.ch> wrote:

> On Thu, Mar 17, 2016 at 09:49:42AM +0100, Boris Brezillon wrote:
> > Hi Daniel,
> > 
> > On Wed, 16 Mar 2016 16:17:38 +0100
> > Daniel Vetter <daniel@ffwll.ch> wrote:
> > 
> > > On Wed, Mar 16, 2016 at 02:57:35PM +0100, Boris Brezillon wrote:
> > > > Add a ->cleanup_fb() operation to avoid memory leaks when the atomic
> > > > operation is interrupted after the ->prepare_fb() call.
> > > > 
> > > > Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> > > > Fixes 2389fc1 ("drm: atmel-hlcdc: Atomic mode-setting conversion")
> > > > Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> > > > Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> > > > ---
> > > >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h    |  2 ++
> > > >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 22 +++++++++++++++++++---
> > > >  2 files changed, 21 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> > > > index fed517f..ec64140 100644
> > > > --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> > > > +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> > > > @@ -81,11 +81,13 @@ struct atmel_hlcdc_plane_properties {
> > > >   * @layer: HLCDC layer structure
> > > >   * @properties: pointer to the property definitions structure
> > > >   * @rotation: current rotation status
> > > > + * @prepared: flagging the plane has prepared for an atomic update
> > > >   */
> > > >  struct atmel_hlcdc_plane {
> > > >  	struct drm_plane base;
> > > >  	struct atmel_hlcdc_layer layer;
> > > >  	struct atmel_hlcdc_plane_properties *properties;
> > > > +	bool prepared;
> > > >  };
> > > >  
> > > >  static inline struct atmel_hlcdc_plane *
> > > > diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> > > > index 1ffe9c3..35027d0 100644
> > > > --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> > > > +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> > > > @@ -715,11 +715,25 @@ static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
> > > >  					const struct drm_plane_state *new_state)
> > > >  {
> > > >  	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
> > > > +	int ret;
> > > >  
> > > > -	if (!new_state->fb)
> > > > -		return 0;
> > > > +	ret = atmel_hlcdc_layer_update_start(&plane->layer);
> > > > +	if (!ret)
> > > > +		plane->prepared = true;
> > > 
> > > Atomic helpers will keep track of this for you, and only call ->cleanup_fb
> > > on a plane combo where it did (successfully) call ->prepare_fb.
> > 
> > Hm, it's not exactly encoding the same thing. What I want to do here is
> > call atmel_hlcdc_layer_update_rollback() only if the atomic update has
> > failed (see below, I set ->prepared back to false in the
> > ->atomic_update() method). AFAICT, ->cleanup_fb() is also called
> > when the whole operation succeed (and in this case I don't want to
> > call atmel_hlcdc_layer_update_rollback()).
> > 
> > Let me know if you see a better approach to do that.
> 
> Ah makes sense. And yeah I guess this is the only approach really. Note
> that you should put plane_prepared into plane_state though, in case we
> start to pipeline updates.

Absolutely, I'll move it to the plane state.

Thanks,

Boris


-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

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

* Re: [PATCH v2 1/9] drm: atmel-hlcdc: add a ->cleanup_fb() operation
  2016-03-18 17:58       ` Daniel Vetter
  2016-03-19 10:48         ` Boris Brezillon
@ 2016-03-30 12:43         ` Boris Brezillon
  1 sibling, 0 replies; 15+ messages in thread
From: Boris Brezillon @ 2016-03-30 12:43 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: David Airlie, dri-devel, Nicolas Ferre,
	Jean-Christophe Plagniol-Villard, Alexandre Belloni,
	linux-arm-kernel, linux-kernel

Hi Daniel,

On Fri, 18 Mar 2016 18:58:48 +0100
Daniel Vetter <daniel@ffwll.ch> wrote:

> On Thu, Mar 17, 2016 at 09:49:42AM +0100, Boris Brezillon wrote:
> > Hi Daniel,
> > 
> > On Wed, 16 Mar 2016 16:17:38 +0100
> > Daniel Vetter <daniel@ffwll.ch> wrote:
> > 
> > > On Wed, Mar 16, 2016 at 02:57:35PM +0100, Boris Brezillon wrote:
> > > > Add a ->cleanup_fb() operation to avoid memory leaks when the atomic
> > > > operation is interrupted after the ->prepare_fb() call.
> > > > 
> > > > Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> > > > Fixes 2389fc1 ("drm: atmel-hlcdc: Atomic mode-setting conversion")
> > > > Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> > > > Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> > > > ---
> > > >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h    |  2 ++
> > > >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 22 +++++++++++++++++++---
> > > >  2 files changed, 21 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> > > > index fed517f..ec64140 100644
> > > > --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> > > > +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> > > > @@ -81,11 +81,13 @@ struct atmel_hlcdc_plane_properties {
> > > >   * @layer: HLCDC layer structure
> > > >   * @properties: pointer to the property definitions structure
> > > >   * @rotation: current rotation status
> > > > + * @prepared: flagging the plane has prepared for an atomic update
> > > >   */
> > > >  struct atmel_hlcdc_plane {
> > > >  	struct drm_plane base;
> > > >  	struct atmel_hlcdc_layer layer;
> > > >  	struct atmel_hlcdc_plane_properties *properties;
> > > > +	bool prepared;
> > > >  };
> > > >  
> > > >  static inline struct atmel_hlcdc_plane *
> > > > diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> > > > index 1ffe9c3..35027d0 100644
> > > > --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> > > > +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> > > > @@ -715,11 +715,25 @@ static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
> > > >  					const struct drm_plane_state *new_state)
> > > >  {
> > > >  	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
> > > > +	int ret;
> > > >  
> > > > -	if (!new_state->fb)
> > > > -		return 0;
> > > > +	ret = atmel_hlcdc_layer_update_start(&plane->layer);
> > > > +	if (!ret)
> > > > +		plane->prepared = true;
> > > 
> > > Atomic helpers will keep track of this for you, and only call ->cleanup_fb
> > > on a plane combo where it did (successfully) call ->prepare_fb.
> > 
> > Hm, it's not exactly encoding the same thing. What I want to do here is
> > call atmel_hlcdc_layer_update_rollback() only if the atomic update has
> > failed (see below, I set ->prepared back to false in the
> > ->atomic_update() method). AFAICT, ->cleanup_fb() is also called
> > when the whole operation succeed (and in this case I don't want to
> > call atmel_hlcdc_layer_update_rollback()).
> > 
> > Let me know if you see a better approach to do that.
> 
> Ah makes sense. And yeah I guess this is the only approach really. Note
> that you should put plane_prepared into plane_state though, in case we
> start to pipeline updates.

Still having a problem when putting the ->prepared field into my
atmel_hlcdc_plane_state struct: ->prepare_fb() and ->cleanup_fb() are
passing a pointer to a *const* struct drm_plane_state, and I'd like to
avoid a const to non-const cast here.


-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

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

end of thread, other threads:[~2016-03-30 12:43 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-16 13:57 [PATCH v2 0/9] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
2016-03-16 13:57 ` [PATCH v2 1/9] drm: atmel-hlcdc: add a ->cleanup_fb() operation Boris Brezillon
2016-03-16 15:17   ` Daniel Vetter
2016-03-17  8:49     ` Boris Brezillon
2016-03-18 17:58       ` Daniel Vetter
2016-03-19 10:48         ` Boris Brezillon
2016-03-30 12:43         ` Boris Brezillon
2016-03-16 13:57 ` [PATCH v2 2/9] drm: atmel-hlcdc: support asynchronous atomic commit operations Boris Brezillon
2016-03-16 13:57 ` [PATCH v2 3/9] drm: atmel-hlcdc: fix connector and encoder types Boris Brezillon
2016-03-16 13:57 ` [PATCH v2 4/9] drm: atmel-hlcdc: remove leftovers from atomic mode setting migration Boris Brezillon
2016-03-16 13:57 ` [PATCH v2 5/9] drm: atmel-hlcdc: support extended timing ranges on sama5d4 and sama5d2 Boris Brezillon
2016-03-16 13:57 ` [PATCH v2 6/9] drm: atmel-hlcdc: move output mode selection in CRTC implementation Boris Brezillon
2016-03-16 13:57 ` [PATCH v2 7/9] drm: atmel-hlcdc: rework the output code to support drm bridges Boris Brezillon
2016-03-16 13:57 ` [PATCH v2 8/9] drm: atmel-hlcdc: check display mode validity in crtc->mode_fixup() Boris Brezillon
2016-03-16 13:57 ` [PATCH v2 9/9] drm: atmel-hlcdc: route DMA accesses through AHB interfaces Boris Brezillon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).