linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements
@ 2016-01-06 10:19 Boris Brezillon
  2016-01-06 10:19 ` [PATCH 1/8] drm: atmel-hlcdc: add a ->cleanup_fb() operation Boris Brezillon
                   ` (9 more replies)
  0 siblings, 10 replies; 18+ messages in thread
From: Boris Brezillon @ 2016-01-06 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

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.

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

Best Regards,

Boris

Boris Brezillon (8):
  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()

 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c   | 148 +++++++++++++-
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c     | 123 ++++++++++-
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h     |  16 ++
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 249 ++++++++++-------------
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c  |  22 +-
 5 files changed, 400 insertions(+), 158 deletions(-)

-- 
2.1.4

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

* [PATCH 1/8] drm: atmel-hlcdc: add a ->cleanup_fb() operation
  2016-01-06 10:19 [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
@ 2016-01-06 10:19 ` Boris Brezillon
  2016-03-08 15:03   ` Nicolas Ferre
  2016-01-06 10:19 ` [PATCH 2/8] drm: atmel-hlcdc: support asynchronous atomic commit operations Boris Brezillon
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 18+ messages in thread
From: Boris Brezillon @ 2016-01-06 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

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")
---
 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 cf6b375..e88e349 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.1.4

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

* [PATCH 2/8] drm: atmel-hlcdc: support asynchronous atomic commit operations
  2016-01-06 10:19 [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
  2016-01-06 10:19 ` [PATCH 1/8] drm: atmel-hlcdc: add a ->cleanup_fb() operation Boris Brezillon
@ 2016-01-06 10:19 ` Boris Brezillon
  2016-01-06 10:19 ` [PATCH 3/8] drm: atmel-hlcdc: fix connector and encoder types Boris Brezillon
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Boris Brezillon @ 2016-01-06 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

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>
---
 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 a45b32b..d760475 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 e88e349..6a762c9 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.1.4

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

* [PATCH 3/8] drm: atmel-hlcdc: fix connector and encoder types
  2016-01-06 10:19 [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
  2016-01-06 10:19 ` [PATCH 1/8] drm: atmel-hlcdc: add a ->cleanup_fb() operation Boris Brezillon
  2016-01-06 10:19 ` [PATCH 2/8] drm: atmel-hlcdc: support asynchronous atomic commit operations Boris Brezillon
@ 2016-01-06 10:19 ` Boris Brezillon
  2016-03-08 15:03   ` Nicolas Ferre
  2016-01-06 10:19 ` [PATCH 4/8] drm: atmel-hlcdc: remove leftovers from atomic mode setting migration Boris Brezillon
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 18+ messages in thread
From: Boris Brezillon @ 2016-01-06 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

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>
---
 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.1.4

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

* [PATCH 4/8] drm: atmel-hlcdc: remove leftovers from atomic mode setting migration
  2016-01-06 10:19 [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
                   ` (2 preceding siblings ...)
  2016-01-06 10:19 ` [PATCH 3/8] drm: atmel-hlcdc: fix connector and encoder types Boris Brezillon
@ 2016-01-06 10:19 ` Boris Brezillon
  2016-03-08 15:04   ` Nicolas Ferre
  2016-01-06 10:19 ` [PATCH 5/8] drm: atmel-hlcdc: support extended timing ranges on sama5d4 and sama5d2 Boris Brezillon
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 18+ messages in thread
From: Boris Brezillon @ 2016-01-06 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

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>
---
 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.1.4

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

* [PATCH 5/8] drm: atmel-hlcdc: support extended timing ranges on sama5d4 and sama5d2
  2016-01-06 10:19 [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
                   ` (3 preceding siblings ...)
  2016-01-06 10:19 ` [PATCH 4/8] drm: atmel-hlcdc: remove leftovers from atomic mode setting migration Boris Brezillon
@ 2016-01-06 10:19 ` Boris Brezillon
  2016-03-08 15:08   ` Nicolas Ferre
  2016-01-06 10:19 ` [PATCH 6/8] drm: atmel-hlcdc: move output mode selection in CRTC implementation Boris Brezillon
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 18+ messages in thread
From: Boris Brezillon @ 2016-01-06 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

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>
---
 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 d760475..66f97e1 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 6a762c9..864791e 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.1.4

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

* [PATCH 6/8] drm: atmel-hlcdc: move output mode selection in CRTC implementation
  2016-01-06 10:19 [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
                   ` (4 preceding siblings ...)
  2016-01-06 10:19 ` [PATCH 5/8] drm: atmel-hlcdc: support extended timing ranges on sama5d4 and sama5d2 Boris Brezillon
@ 2016-01-06 10:19 ` Boris Brezillon
  2016-01-06 10:19 ` [PATCH 7/8] drm: atmel-hlcdc: rework the output code to support drm bridges Boris Brezillon
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Boris Brezillon @ 2016-01-06 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

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>
---
 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 468a14f..be30bd2 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);
 }
 
@@ -318,13 +403,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 66f97e1..3f8bfa6 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 864791e..eabf9c6 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.1.4

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

* [PATCH 7/8] drm: atmel-hlcdc: rework the output code to support drm bridges
  2016-01-06 10:19 [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
                   ` (5 preceding siblings ...)
  2016-01-06 10:19 ` [PATCH 6/8] drm: atmel-hlcdc: move output mode selection in CRTC implementation Boris Brezillon
@ 2016-01-06 10:19 ` Boris Brezillon
  2016-01-06 10:19 ` [PATCH 8/8] drm: atmel-hlcdc: check display mode validity in crtc->mode_fixup() Boris Brezillon
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Boris Brezillon @ 2016-01-06 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

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>
---
 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 3f8bfa6..d004751 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.1.4

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

* [PATCH 8/8] drm: atmel-hlcdc: check display mode validity in crtc->mode_fixup()
  2016-01-06 10:19 [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
                   ` (6 preceding siblings ...)
  2016-01-06 10:19 ` [PATCH 7/8] drm: atmel-hlcdc: rework the output code to support drm bridges Boris Brezillon
@ 2016-01-06 10:19 ` Boris Brezillon
  2016-03-08 15:44   ` Nicolas Ferre
  2016-03-01 10:55 ` [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
  2016-03-16 13:06 ` Nicolas Ferre
  9 siblings, 1 reply; 18+ messages in thread
From: Boris Brezillon @ 2016-01-06 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.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 be30bd2..d5a028f 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.1.4

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

* [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements
  2016-01-06 10:19 [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
                   ` (7 preceding siblings ...)
  2016-01-06 10:19 ` [PATCH 8/8] drm: atmel-hlcdc: check display mode validity in crtc->mode_fixup() Boris Brezillon
@ 2016-03-01 10:55 ` Boris Brezillon
  2016-03-17  2:43   ` Dave Airlie
  2016-03-16 13:06 ` Nicolas Ferre
  9 siblings, 1 reply; 18+ messages in thread
From: Boris Brezillon @ 2016-03-01 10:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed,  6 Jan 2016 11:19:21 +0100
Boris Brezillon <boris.brezillon@free-electrons.com> wrote:

> 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.
> 
> And patch 8 is just a cosmetic patch moving the mode checking code
> from ->atomic_check() to ->mode_fixup().

Dave, Daniel, any comment on this series (AKA ping)?

> 
> Best Regards,
> 
> Boris
> 
> Boris Brezillon (8):
>   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()
> 
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c   | 148 +++++++++++++-
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c     | 123 ++++++++++-
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h     |  16 ++
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 249 ++++++++++-------------
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c  |  22 +-
>  5 files changed, 400 insertions(+), 158 deletions(-)
> 



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

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

* [PATCH 3/8] drm: atmel-hlcdc: fix connector and encoder types
  2016-01-06 10:19 ` [PATCH 3/8] drm: atmel-hlcdc: fix connector and encoder types Boris Brezillon
@ 2016-03-08 15:03   ` Nicolas Ferre
  0 siblings, 0 replies; 18+ messages in thread
From: Nicolas Ferre @ 2016-03-08 15:03 UTC (permalink / raw)
  To: linux-arm-kernel

Le 06/01/2016 11:19, Boris Brezillon a ?crit :
> 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>

Yes:
Acked-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;
>  
> 


-- 
Nicolas Ferre

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

* [PATCH 1/8] drm: atmel-hlcdc: add a ->cleanup_fb() operation
  2016-01-06 10:19 ` [PATCH 1/8] drm: atmel-hlcdc: add a ->cleanup_fb() operation Boris Brezillon
@ 2016-03-08 15:03   ` Nicolas Ferre
  0 siblings, 0 replies; 18+ messages in thread
From: Nicolas Ferre @ 2016-03-08 15:03 UTC (permalink / raw)
  To: linux-arm-kernel

Le 06/01/2016 11:19, Boris Brezillon a ?crit :
> 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")

Seems okay:
Reviewed-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 cf6b375..e88e349 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,
> 


-- 
Nicolas Ferre

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

* [PATCH 4/8] drm: atmel-hlcdc: remove leftovers from atomic mode setting migration
  2016-01-06 10:19 ` [PATCH 4/8] drm: atmel-hlcdc: remove leftovers from atomic mode setting migration Boris Brezillon
@ 2016-03-08 15:04   ` Nicolas Ferre
  0 siblings, 0 replies; 18+ messages in thread
From: Nicolas Ferre @ 2016-03-08 15:04 UTC (permalink / raw)
  To: linux-arm-kernel

Le 06/01/2016 11:19, Boris Brezillon a ?crit :
> 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>

> ---
>  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;
>  
> 


-- 
Nicolas Ferre

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

* [PATCH 5/8] drm: atmel-hlcdc: support extended timing ranges on sama5d4 and sama5d2
  2016-01-06 10:19 ` [PATCH 5/8] drm: atmel-hlcdc: support extended timing ranges on sama5d4 and sama5d2 Boris Brezillon
@ 2016-03-08 15:08   ` Nicolas Ferre
  0 siblings, 0 replies; 18+ messages in thread
From: Nicolas Ferre @ 2016-03-08 15:08 UTC (permalink / raw)
  To: linux-arm-kernel

Le 06/01/2016 11:19, Boris Brezillon a ?crit :
> 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>

Absolutely:
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>

Thanks.


> ---
>  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 d760475..66f97e1 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 6a762c9..864791e 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;
>  };
> 


-- 
Nicolas Ferre

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

* [PATCH 8/8] drm: atmel-hlcdc: check display mode validity in crtc->mode_fixup()
  2016-01-06 10:19 ` [PATCH 8/8] drm: atmel-hlcdc: check display mode validity in crtc->mode_fixup() Boris Brezillon
@ 2016-03-08 15:44   ` Nicolas Ferre
  0 siblings, 0 replies; 18+ messages in thread
From: Nicolas Ferre @ 2016-03-08 15:44 UTC (permalink / raw)
  To: linux-arm-kernel

Le 06/01/2016 11:19, Boris Brezillon a ?crit :
> Move the adjusted display mode check into ->mode_fixup().
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>

Seems okay:
Acked-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 be30bd2..d5a028f 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;
> 


-- 
Nicolas Ferre

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

* [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements
  2016-01-06 10:19 [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
                   ` (8 preceding siblings ...)
  2016-03-01 10:55 ` [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
@ 2016-03-16 13:06 ` Nicolas Ferre
  9 siblings, 0 replies; 18+ messages in thread
From: Nicolas Ferre @ 2016-03-16 13:06 UTC (permalink / raw)
  To: linux-arm-kernel

Le 06/01/2016 11:19, Boris Brezillon a ?crit :
> 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.
> 
> And patch 8 is just a cosmetic patch moving the mode checking code
> from ->atomic_check() to ->mode_fixup().

To give more weight to this series, you can also add my:

Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>

Bye,


> Boris Brezillon (8):
>   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()
> 
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c   | 148 +++++++++++++-
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c     | 123 ++++++++++-
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h     |  16 ++
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 249 ++++++++++-------------
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c  |  22 +-
>  5 files changed, 400 insertions(+), 158 deletions(-)
> 


-- 
Nicolas Ferre

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

* [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements
  2016-03-01 10:55 ` [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
@ 2016-03-17  2:43   ` Dave Airlie
  2016-03-17  8:33     ` Boris Brezillon
  0 siblings, 1 reply; 18+ messages in thread
From: Dave Airlie @ 2016-03-17  2:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 1 March 2016 at 20:55, Boris Brezillon
<boris.brezillon@free-electrons.com> wrote:
> On Wed,  6 Jan 2016 11:19:21 +0100
> Boris Brezillon <boris.brezillon@free-electrons.com> wrote:
>
>> 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.
>>
>> And patch 8 is just a cosmetic patch moving the mode checking code
>> from ->atomic_check() to ->mode_fixup().
>
> Dave, Daniel, any comment on this series (AKA ping)?

On internal driver stuff, I'd usually only look on a git pull :-)

Dave.

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

* [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements
  2016-03-17  2:43   ` Dave Airlie
@ 2016-03-17  8:33     ` Boris Brezillon
  0 siblings, 0 replies; 18+ messages in thread
From: Boris Brezillon @ 2016-03-17  8:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 17 Mar 2016 12:43:11 +1000
Dave Airlie <airlied@gmail.com> wrote:

> On 1 March 2016 at 20:55, Boris Brezillon
> <boris.brezillon@free-electrons.com> wrote:
> > On Wed,  6 Jan 2016 11:19:21 +0100
> > Boris Brezillon <boris.brezillon@free-electrons.com> wrote:
> >
> >> 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.
> >>
> >> And patch 8 is just a cosmetic patch moving the mode checking code
> >> from ->atomic_check() to ->mode_fixup().
> >
> > Dave, Daniel, any comment on this series (AKA ping)?
> 
> On internal driver stuff, I'd usually only look on a git pull :-)

Yep, Daniel told me that both of you usually don't review internal
driver changes. I'll send a PR soon (after the merge window of course).

Thanks,

Boris

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

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

end of thread, other threads:[~2016-03-17  8:33 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-01-06 10:19 [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
2016-01-06 10:19 ` [PATCH 1/8] drm: atmel-hlcdc: add a ->cleanup_fb() operation Boris Brezillon
2016-03-08 15:03   ` Nicolas Ferre
2016-01-06 10:19 ` [PATCH 2/8] drm: atmel-hlcdc: support asynchronous atomic commit operations Boris Brezillon
2016-01-06 10:19 ` [PATCH 3/8] drm: atmel-hlcdc: fix connector and encoder types Boris Brezillon
2016-03-08 15:03   ` Nicolas Ferre
2016-01-06 10:19 ` [PATCH 4/8] drm: atmel-hlcdc: remove leftovers from atomic mode setting migration Boris Brezillon
2016-03-08 15:04   ` Nicolas Ferre
2016-01-06 10:19 ` [PATCH 5/8] drm: atmel-hlcdc: support extended timing ranges on sama5d4 and sama5d2 Boris Brezillon
2016-03-08 15:08   ` Nicolas Ferre
2016-01-06 10:19 ` [PATCH 6/8] drm: atmel-hlcdc: move output mode selection in CRTC implementation Boris Brezillon
2016-01-06 10:19 ` [PATCH 7/8] drm: atmel-hlcdc: rework the output code to support drm bridges Boris Brezillon
2016-01-06 10:19 ` [PATCH 8/8] drm: atmel-hlcdc: check display mode validity in crtc->mode_fixup() Boris Brezillon
2016-03-08 15:44   ` Nicolas Ferre
2016-03-01 10:55 ` [PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements Boris Brezillon
2016-03-17  2:43   ` Dave Airlie
2016-03-17  8:33     ` Boris Brezillon
2016-03-16 13:06 ` Nicolas Ferre

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).