linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/18] Armada DRM updates
@ 2019-06-13 15:01 Russell King - ARM Linux admin
  2019-06-13 15:01 ` [PATCH 01/18] drm/armada: fix crtc interlace Russell King
                   ` (17 more replies)
  0 siblings, 18 replies; 19+ messages in thread
From: Russell King - ARM Linux admin @ 2019-06-13 15:01 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Hi,

This series updates Armada DRM:

- Fix interlace support.
- use __drm_atomic_helper_plane_reset in overlay reset.
- since the overlay and video planes use essentially the same format
  registers, precompute their values while validating.
- fix a long-standing deficiency with overlay planes and interlace modes
- calculate plane starting address at atomic_check stage rather than
  when we're programming the registers.
- add gamma support.
- ensure mode adjustments made by other components are properly handled
  in the driver and applied to the CRTC-programmed mode.
- add and use register definitions for the "REG4F" register.
- use drm_atomic_helper_shutdown() when tearing down to ensure that the
  hardware is properly shutdown.
- add CRTC-level mode validation to ensure that we don't allow a mode
  that the CRTC-level hardware can not support.
- improve the clocking selection for Armada 510 support.
- move CRTC debugfs files into the crtc-specific directory, using the
  DRM helper to create these files.
- patch from Lubomir Rintel to replace a simple framebuffer.
- use the OF graph walker rather than open-coding this.
- eliminate a useless check for the availability of the remote's parent
  which isn't required.

 drivers/gpu/drm/armada/armada_510.c     | 130 ++++++++++++++------
 drivers/gpu/drm/armada/armada_crtc.c    | 212 ++++++++++++++++++++++++++++++--
 drivers/gpu/drm/armada/armada_crtc.h    |  21 +++-
 drivers/gpu/drm/armada/armada_debugfs.c |  98 ++++++---------
 drivers/gpu/drm/armada/armada_drm.h     |   1 +
 drivers/gpu/drm/armada/armada_drv.c     |  38 +++---
 drivers/gpu/drm/armada/armada_hw.h      |  29 +++--
 drivers/gpu/drm/armada/armada_overlay.c |  56 ++++-----
 drivers/gpu/drm/armada/armada_plane.c   | 124 +++++++++++++------
 drivers/gpu/drm/armada/armada_plane.h   |  23 ++++
 10 files changed, 520 insertions(+), 212 deletions(-)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 01/18] drm/armada: fix crtc interlace
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
@ 2019-06-13 15:01 ` Russell King
  2019-06-13 15:01 ` [PATCH 02/18] drm/armada: use __drm_atomic_helper_plane_reset in overlay reset Russell King
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:01 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

We support interlace, but this was broken when we could no longer get
a ref on the vblank interrupt.  Arrange to get the ref on the vblank
interrupt after we've re-enabled vblank, and put it before we disable
the vblank.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_crtc.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index ba4a3fab7745..09bade15f51c 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -278,16 +278,9 @@ static void armada_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
 
 	armada_reg_queue_set(regs, i, sclk, LCD_CFG_SCLK_DIV);
 
-	if (interlaced ^ dcrtc->interlaced) {
-		if (adj->flags & DRM_MODE_FLAG_INTERLACE)
-			drm_crtc_vblank_get(&dcrtc->crtc);
-		else
-			drm_crtc_vblank_put(&dcrtc->crtc);
-		dcrtc->interlaced = interlaced;
-	}
-
 	spin_lock_irqsave(&dcrtc->irq_lock, flags);
 
+	dcrtc->interlaced = interlaced;
 	/* Even interlaced/progressive frame */
 	dcrtc->v[1].spu_v_h_total = adj->crtc_vtotal << 16 |
 				    adj->crtc_htotal;
@@ -390,6 +383,9 @@ static void armada_drm_crtc_atomic_disable(struct drm_crtc *crtc,
 
 	DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
 
+	if (old_state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
+		drm_crtc_vblank_put(crtc);
+
 	drm_crtc_vblank_off(crtc);
 	armada_drm_crtc_update(dcrtc, false);
 
@@ -434,6 +430,9 @@ static void armada_drm_crtc_atomic_enable(struct drm_crtc *crtc,
 	armada_drm_crtc_update(dcrtc, true);
 	drm_crtc_vblank_on(crtc);
 
+	if (crtc->state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
+		WARN_ON(drm_crtc_vblank_get(crtc));
+
 	armada_drm_crtc_queue_state_event(crtc);
 }
 
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 02/18] drm/armada: use __drm_atomic_helper_plane_reset in overlay reset
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
  2019-06-13 15:01 ` [PATCH 01/18] drm/armada: fix crtc interlace Russell King
@ 2019-06-13 15:01 ` Russell King
  2019-06-13 15:01 ` [PATCH 03/18] drm/armada: add plane size/location accessors Russell King
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:01 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Use the __drm_atomic_helper_plane_reset() helper in the overlay reset
code to ensure that generic features are correctly reset in future.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_overlay.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 8d770641fcc4..f830f53d7adf 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -307,13 +307,10 @@ static void armada_overlay_reset(struct drm_plane *plane)
 	if (plane->state)
 		__drm_atomic_helper_plane_destroy_state(plane->state);
 	kfree(plane->state);
+	plane->state = NULL;
 
 	state = kzalloc(sizeof(*state), GFP_KERNEL);
 	if (state) {
-		state->base.plane = plane;
-		state->base.color_encoding = DEFAULT_ENCODING;
-		state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
-		state->base.rotation = DRM_MODE_ROTATE_0;
 		state->colorkey_yr = 0xfefefe00;
 		state->colorkey_ug = 0x01010100;
 		state->colorkey_vb = 0x01010100;
@@ -323,8 +320,10 @@ static void armada_overlay_reset(struct drm_plane *plane)
 		state->brightness = DEFAULT_BRIGHTNESS;
 		state->contrast = DEFAULT_CONTRAST;
 		state->saturation = DEFAULT_SATURATION;
+		__drm_atomic_helper_plane_reset(plane, &state->base);
+		state->base.color_encoding = DEFAULT_ENCODING;
+		state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
 	}
-	plane->state = &state->base;
 }
 
 struct drm_plane_state *
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 03/18] drm/armada: add plane size/location accessors
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
  2019-06-13 15:01 ` [PATCH 01/18] drm/armada: fix crtc interlace Russell King
  2019-06-13 15:01 ` [PATCH 02/18] drm/armada: use __drm_atomic_helper_plane_reset in overlay reset Russell King
@ 2019-06-13 15:01 ` Russell King
  2019-06-13 15:02 ` [PATCH 04/18] drm/armada: fix plane location and size for interlace Russell King
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:01 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Add accessors for getting the register values for the plane from the
plane state.  This will allow us to generate the values when validating
the plane rather than when programming, which allows us to fix the
interlace handling without adding lots of additional handling in the
update functions.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_overlay.c | 12 ++++++------
 drivers/gpu/drm/armada/armada_plane.c   | 12 ++++++------
 drivers/gpu/drm/armada/armada_plane.h   |  4 ++++
 3 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index f830f53d7adf..8a3d2815cb58 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -94,14 +94,14 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
 		armada_reg_queue_mod(regs, idx,
 				     0, CFG_PDWN16x66 | CFG_PDWN32x66,
 				     LCD_SPU_SRAM_PARA1);
-	val = armada_rect_hw_fp(&state->src);
-	if (armada_rect_hw_fp(&old_state->src) != val)
+	val = armada_src_hw(state);
+	if (armada_src_hw(old_state) != val)
 		armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_HPXL_VLN);
-	val = armada_rect_yx(&state->dst);
-	if (armada_rect_yx(&old_state->dst) != val)
+	val = armada_dst_yx(state);
+	if (armada_dst_yx(old_state) != val)
 		armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_OVSA_HPXL_VLN);
-	val = armada_rect_hw(&state->dst);
-	if (armada_rect_hw(&old_state->dst) != val)
+	val = armada_dst_hw(state);
+	if (armada_dst_hw(old_state) != val)
 		armada_reg_queue_set(regs, idx, val, LCD_SPU_DZM_HPXL_VLN);
 	/* FIXME: overlay on an interlaced display */
 	if (old_state->src.x1 != state->src.x1 ||
diff --git a/drivers/gpu/drm/armada/armada_plane.c b/drivers/gpu/drm/armada/armada_plane.c
index 9f36423dd394..6c098d379ae2 100644
--- a/drivers/gpu/drm/armada/armada_plane.c
+++ b/drivers/gpu/drm/armada/armada_plane.c
@@ -173,14 +173,14 @@ static void armada_drm_primary_plane_atomic_update(struct drm_plane *plane,
 			val |= CFG_PDWN256x24;
 		armada_reg_queue_mod(regs, idx, 0, val, LCD_SPU_SRAM_PARA1);
 	}
-	val = armada_rect_hw_fp(&state->src);
-	if (armada_rect_hw_fp(&old_state->src) != val)
+	val = armada_src_hw(state);
+	if (armada_src_hw(old_state) != val)
 		armada_reg_queue_set(regs, idx, val, LCD_SPU_GRA_HPXL_VLN);
-	val = armada_rect_yx(&state->dst);
-	if (armada_rect_yx(&old_state->dst) != val)
+	val = armada_dst_yx(state);
+	if (armada_dst_yx(old_state) != val)
 		armada_reg_queue_set(regs, idx, val, LCD_SPU_GRA_OVSA_HPXL_VLN);
-	val = armada_rect_hw(&state->dst);
-	if (armada_rect_hw(&old_state->dst) != val)
+	val = armada_dst_hw(state);
+	if (armada_dst_hw(old_state) != val)
 		armada_reg_queue_set(regs, idx, val, LCD_SPU_GZM_HPXL_VLN);
 	if (old_state->src.x1 != state->src.x1 ||
 	    old_state->src.y1 != state->src.y1 ||
diff --git a/drivers/gpu/drm/armada/armada_plane.h b/drivers/gpu/drm/armada/armada_plane.h
index ff4281ba7fad..049c593342eb 100644
--- a/drivers/gpu/drm/armada/armada_plane.h
+++ b/drivers/gpu/drm/armada/armada_plane.h
@@ -1,6 +1,10 @@
 #ifndef ARMADA_PLANE_H
 #define ARMADA_PLANE_H
 
+#define armada_src_hw(state)	armada_rect_hw_fp(&(state)->src)
+#define armada_dst_yx(state)	armada_rect_yx(&(state)->dst)
+#define armada_dst_hw(state)	armada_rect_hw(&(state)->dst)
+
 void armada_drm_plane_calc(struct drm_plane_state *state, u32 addrs[2][3],
 	u16 pitches[3], bool interlaced);
 int armada_drm_plane_prepare_fb(struct drm_plane *plane,
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 04/18] drm/armada: fix plane location and size for interlace
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (2 preceding siblings ...)
  2019-06-13 15:01 ` [PATCH 03/18] drm/armada: add plane size/location accessors Russell King
@ 2019-06-13 15:02 ` Russell King
  2019-06-13 15:02 ` [PATCH 05/18] drm/armada: add missing interlaced support for overlay frame Russell King
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:02 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

When the CRTC is programmed for interlace, we have to halve the Y
parameters for the plane.  Rather than doing this in the update
function (which would need the calculation repeated for the old
state as well as the new state), arrange to do the calculation in
atomic_check and save it in our private plane state structure.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_hw.h      | 15 -------
 drivers/gpu/drm/armada/armada_overlay.c | 15 ++++---
 drivers/gpu/drm/armada/armada_plane.c   | 80 +++++++++++++++++++++++++++------
 drivers/gpu/drm/armada/armada_plane.h   | 20 +++++++--
 4 files changed, 91 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h
index 277580b36758..345dc4d0851e 100644
--- a/drivers/gpu/drm/armada/armada_hw.h
+++ b/drivers/gpu/drm/armada/armada_hw.h
@@ -316,19 +316,4 @@ enum {
 	PWRDN_IRQ_LEVEL		= 1 << 0,
 };
 
-static inline u32 armada_rect_hw_fp(struct drm_rect *r)
-{
-	return (drm_rect_height(r) & 0xffff0000) | drm_rect_width(r) >> 16;
-}
-
-static inline u32 armada_rect_hw(struct drm_rect *r)
-{
-	return drm_rect_height(r) << 16 | (drm_rect_width(r) & 0x0000ffff);
-}
-
-static inline u32 armada_rect_yx(struct drm_rect *r)
-{
-	return (r)->y1 << 16 | ((r)->x1 & 0x0000ffff);
-}
-
 #endif
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 8a3d2815cb58..589cdb6a9dae 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -27,7 +27,7 @@
 #define DEFAULT_ENCODING	DRM_COLOR_YCBCR_BT601
 
 struct armada_overlay_state {
-	struct drm_plane_state base;
+	struct armada_plane_state base;
 	u32 colorkey_yr;
 	u32 colorkey_ug;
 	u32 colorkey_vb;
@@ -38,7 +38,7 @@ struct armada_overlay_state {
 	u16 saturation;
 };
 #define drm_to_overlay_state(s) \
-	container_of(s, struct armada_overlay_state, base)
+	container_of(s, struct armada_overlay_state, base.base)
 
 static inline u32 armada_spu_contrast(struct drm_plane_state *state)
 {
@@ -320,9 +320,9 @@ static void armada_overlay_reset(struct drm_plane *plane)
 		state->brightness = DEFAULT_BRIGHTNESS;
 		state->contrast = DEFAULT_CONTRAST;
 		state->saturation = DEFAULT_SATURATION;
-		__drm_atomic_helper_plane_reset(plane, &state->base);
-		state->base.color_encoding = DEFAULT_ENCODING;
-		state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
+		__drm_atomic_helper_plane_reset(plane, &state->base.base);
+		state->base.base.color_encoding = DEFAULT_ENCODING;
+		state->base.base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
 	}
 }
 
@@ -336,8 +336,9 @@ armada_overlay_duplicate_state(struct drm_plane *plane)
 
 	state = kmemdup(plane->state, sizeof(*state), GFP_KERNEL);
 	if (state)
-		__drm_atomic_helper_plane_duplicate_state(plane, &state->base);
-	return &state->base;
+		__drm_atomic_helper_plane_duplicate_state(plane,
+							  &state->base.base);
+	return &state->base.base;
 }
 
 static int armada_overlay_set_property(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/armada/armada_plane.c b/drivers/gpu/drm/armada/armada_plane.c
index 6c098d379ae2..09218c1d8a4b 100644
--- a/drivers/gpu/drm/armada/armada_plane.c
+++ b/drivers/gpu/drm/armada/armada_plane.c
@@ -126,20 +126,47 @@ void armada_drm_plane_cleanup_fb(struct drm_plane *plane,
 int armada_drm_plane_atomic_check(struct drm_plane *plane,
 	struct drm_plane_state *state)
 {
-	if (state->fb && !WARN_ON(!state->crtc)) {
-		struct drm_crtc *crtc = state->crtc;
-		struct drm_crtc_state *crtc_state;
-
-		if (state->state)
-			crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
-		else
-			crtc_state = crtc->state;
-		return drm_atomic_helper_check_plane_state(state, crtc_state,
-							   0, INT_MAX,
-							   true, false);
-	} else {
+	struct armada_plane_state *st = to_armada_plane_state(state);
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_crtc_state *crtc_state;
+	bool interlace;
+	int ret;
+
+	if (!state->fb || WARN_ON(!state->crtc)) {
 		state->visible = false;
+		return 0;
 	}
+
+	if (state->state)
+		crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
+	else
+		crtc_state = crtc->state;
+
+	ret = drm_atomic_helper_check_plane_state(state, crtc_state, 0,
+						  INT_MAX, true, false);
+	if (ret)
+		return ret;
+
+	interlace = crtc_state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE;
+	if (interlace) {
+		if ((state->dst.y1 | state->dst.y2) & 1)
+			return -EINVAL;
+		st->src_hw = drm_rect_height(&state->src) >> 17;
+		st->dst_yx = state->dst.y1 >> 1;
+		st->dst_hw = drm_rect_height(&state->dst) >> 1;
+	} else {
+		st->src_hw = drm_rect_height(&state->src) >> 16;
+		st->dst_yx = state->dst.y1;
+		st->dst_hw = drm_rect_height(&state->dst);
+	}
+
+	st->src_hw <<= 16;
+	st->src_hw |= drm_rect_width(&state->src) >> 16;
+	st->dst_yx <<= 16;
+	st->dst_yx |= state->dst.x1 & 0x0000ffff;
+	st->dst_hw <<= 16;
+	st->dst_hw |= drm_rect_width(&state->dst) & 0x0000ffff;
+
 	return 0;
 }
 
@@ -262,12 +289,37 @@ static const struct drm_plane_helper_funcs armada_primary_plane_helper_funcs = {
 	.atomic_disable	= armada_drm_primary_plane_atomic_disable,
 };
 
+void armada_plane_reset(struct drm_plane *plane)
+{
+	struct armada_plane_state *st;
+	if (plane->state)
+		__drm_atomic_helper_plane_destroy_state(plane->state);
+	kfree(plane->state);
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (st)
+		__drm_atomic_helper_plane_reset(plane, &st->base);
+}
+
+struct drm_plane_state *armada_plane_duplicate_state(struct drm_plane *plane)
+{
+	struct armada_plane_state *st;
+
+	if (WARN_ON(!plane->state))
+		return NULL;
+
+	st = kmemdup(plane->state, sizeof(*st), GFP_KERNEL);
+	if (st)
+		__drm_atomic_helper_plane_duplicate_state(plane, &st->base);
+
+	return &st->base;
+}
+
 static const struct drm_plane_funcs armada_primary_plane_funcs = {
 	.update_plane	= drm_atomic_helper_update_plane,
 	.disable_plane	= drm_atomic_helper_disable_plane,
 	.destroy	= drm_primary_helper_destroy,
-	.reset		= drm_atomic_helper_plane_reset,
-	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.reset		= armada_plane_reset,
+	.atomic_duplicate_state = armada_plane_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
 };
 
diff --git a/drivers/gpu/drm/armada/armada_plane.h b/drivers/gpu/drm/armada/armada_plane.h
index 049c593342eb..396c45a4ea5e 100644
--- a/drivers/gpu/drm/armada/armada_plane.h
+++ b/drivers/gpu/drm/armada/armada_plane.h
@@ -1,9 +1,18 @@
 #ifndef ARMADA_PLANE_H
 #define ARMADA_PLANE_H
 
-#define armada_src_hw(state)	armada_rect_hw_fp(&(state)->src)
-#define armada_dst_yx(state)	armada_rect_yx(&(state)->dst)
-#define armada_dst_hw(state)	armada_rect_hw(&(state)->dst)
+struct armada_plane_state {
+	struct drm_plane_state base;
+	u32 src_hw;
+	u32 dst_yx;
+	u32 dst_hw;
+};
+
+#define to_armada_plane_state(st) \
+	container_of(st, struct armada_plane_state, base)
+#define armada_src_hw(state) to_armada_plane_state(state)->src_hw
+#define armada_dst_yx(state) to_armada_plane_state(state)->dst_yx
+#define armada_dst_hw(state) to_armada_plane_state(state)->dst_hw
 
 void armada_drm_plane_calc(struct drm_plane_state *state, u32 addrs[2][3],
 	u16 pitches[3], bool interlaced);
@@ -13,6 +22,11 @@ void armada_drm_plane_cleanup_fb(struct drm_plane *plane,
 	struct drm_plane_state *old_state);
 int armada_drm_plane_atomic_check(struct drm_plane *plane,
 	struct drm_plane_state *state);
+void armada_plane_reset(struct drm_plane *plane);
+struct drm_plane_state *armada_plane_duplicate_state(struct drm_plane *plane);
+void armada_plane_destroy_state(struct drm_plane *plane,
+				struct drm_plane_state *state);
+
 int armada_drm_primary_plane_init(struct drm_device *drm,
 	struct drm_plane *primary);
 
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 05/18] drm/armada: add missing interlaced support for overlay frame
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (3 preceding siblings ...)
  2019-06-13 15:02 ` [PATCH 04/18] drm/armada: fix plane location and size for interlace Russell King
@ 2019-06-13 15:02 ` Russell King
  2019-06-13 15:02 ` [PATCH 06/18] drm/armada: move plane address and pitch calculation to atomic_check Russell King
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:02 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Interlaced support has been missing from the overlay frame, which is
sub-optimal.  Add support for this missing feature.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_overlay.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 589cdb6a9dae..d8d6e4645c1f 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -106,12 +106,13 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
 	/* FIXME: overlay on an interlaced display */
 	if (old_state->src.x1 != state->src.x1 ||
 	    old_state->src.y1 != state->src.y1 ||
-	    old_state->fb != state->fb) {
+	    old_state->fb != state->fb ||
+	    state->crtc->state->mode_changed) {
 		const struct drm_format_info *format;
 		u16 src_x, pitches[3];
 		u32 addrs[2][3];
 
-		armada_drm_plane_calc(state, addrs, pitches, false);
+		armada_drm_plane_calc(state, addrs, pitches, dcrtc->interlaced);
 
 		armada_reg_queue_set(regs, idx, addrs[0][0],
 				     LCD_SPU_DMA_START_ADDR_Y0);
@@ -146,6 +147,8 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
 		src_x = state->src.x1 >> 16;
 		if (format->num_planes == 1 && src_x & (format->hsub - 1))
 			cfg ^= CFG_DMA_MOD(CFG_SWAPUV);
+		if (dcrtc->interlaced)
+			cfg |= CFG_DMA_FTOGGLE;
 		cfg_mask = CFG_CBSH_ENA | CFG_DMAFORMAT |
 			   CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV |
 				       CFG_SWAPYU | CFG_YUV2RGB) |
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 06/18] drm/armada: move plane address and pitch calculation to atomic_check
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (4 preceding siblings ...)
  2019-06-13 15:02 ` [PATCH 05/18] drm/armada: add missing interlaced support for overlay frame Russell King
@ 2019-06-13 15:02 ` Russell King
  2019-06-13 15:02 ` [PATCH 07/18] drm/armada: add support for setting gamma Russell King
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:02 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Move the plane address and pitch calculations to atomic_check rather
than the update function, so we don't have to probe the interlace
setting for the CRTC while updating the plane.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_overlay.c | 23 ++++++++++-------------
 drivers/gpu/drm/armada/armada_plane.c   | 30 ++++++++++--------------------
 drivers/gpu/drm/armada/armada_plane.h   |  5 +++++
 3 files changed, 25 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index d8d6e4645c1f..a79d6e940435 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -109,27 +109,24 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
 	    old_state->fb != state->fb ||
 	    state->crtc->state->mode_changed) {
 		const struct drm_format_info *format;
-		u16 src_x, pitches[3];
-		u32 addrs[2][3];
+		u16 src_x;
 
-		armada_drm_plane_calc(state, addrs, pitches, dcrtc->interlaced);
-
-		armada_reg_queue_set(regs, idx, addrs[0][0],
+		armada_reg_queue_set(regs, idx, armada_addr(state, 0, 0),
 				     LCD_SPU_DMA_START_ADDR_Y0);
-		armada_reg_queue_set(regs, idx, addrs[0][1],
+		armada_reg_queue_set(regs, idx, armada_addr(state, 0, 1),
 				     LCD_SPU_DMA_START_ADDR_U0);
-		armada_reg_queue_set(regs, idx, addrs[0][2],
+		armada_reg_queue_set(regs, idx, armada_addr(state, 0, 2),
 				     LCD_SPU_DMA_START_ADDR_V0);
-		armada_reg_queue_set(regs, idx, addrs[1][0],
+		armada_reg_queue_set(regs, idx, armada_addr(state, 1, 0),
 				     LCD_SPU_DMA_START_ADDR_Y1);
-		armada_reg_queue_set(regs, idx, addrs[1][1],
+		armada_reg_queue_set(regs, idx, armada_addr(state, 1, 1),
 				     LCD_SPU_DMA_START_ADDR_U1);
-		armada_reg_queue_set(regs, idx, addrs[1][2],
+		armada_reg_queue_set(regs, idx, armada_addr(state, 1, 2),
 				     LCD_SPU_DMA_START_ADDR_V1);
 
-		val = pitches[0] << 16 | pitches[0];
+		val = armada_pitch(state, 0) << 16 | armada_pitch(state, 0);
 		armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_PITCH_YC);
-		val = pitches[1] << 16 | pitches[2];
+		val = armada_pitch(state, 1) << 16 | armada_pitch(state, 2);
 		armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_PITCH_UV);
 
 		cfg = CFG_DMA_FMT(drm_fb_to_armada_fb(state->fb)->fmt) |
@@ -147,7 +144,7 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
 		src_x = state->src.x1 >> 16;
 		if (format->num_planes == 1 && src_x & (format->hsub - 1))
 			cfg ^= CFG_DMA_MOD(CFG_SWAPUV);
-		if (dcrtc->interlaced)
+		if (to_armada_plane_state(state)->interlace)
 			cfg |= CFG_DMA_FTOGGLE;
 		cfg_mask = CFG_CBSH_ENA | CFG_DMAFORMAT |
 			   CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV |
diff --git a/drivers/gpu/drm/armada/armada_plane.c b/drivers/gpu/drm/armada/armada_plane.c
index 09218c1d8a4b..45092fc3598e 100644
--- a/drivers/gpu/drm/armada/armada_plane.c
+++ b/drivers/gpu/drm/armada/armada_plane.c
@@ -79,23 +79,6 @@ void armada_drm_plane_calc(struct drm_plane_state *state, u32 addrs[2][3],
 	}
 }
 
-static unsigned armada_drm_crtc_calc_fb(struct drm_plane_state *state,
-	struct armada_regs *regs, bool interlaced)
-{
-	u16 pitches[3];
-	u32 addrs[2][3];
-	unsigned i = 0;
-
-	armada_drm_plane_calc(state, addrs, pitches, interlaced);
-
-	/* write offset, base, and pitch */
-	armada_reg_queue_set(regs, i, addrs[0][0], LCD_CFG_GRA_START_ADDR0);
-	armada_reg_queue_set(regs, i, addrs[1][0], LCD_CFG_GRA_START_ADDR1);
-	armada_reg_queue_mod(regs, i, pitches[0], 0xffff, LCD_CFG_GRA_PITCH);
-
-	return i;
-}
-
 int armada_drm_plane_prepare_fb(struct drm_plane *plane,
 	struct drm_plane_state *state)
 {
@@ -167,6 +150,9 @@ int armada_drm_plane_atomic_check(struct drm_plane *plane,
 	st->dst_hw <<= 16;
 	st->dst_hw |= drm_rect_width(&state->dst) & 0x0000ffff;
 
+	armada_drm_plane_calc(state, st->addrs, st->pitches, interlace);
+	st->interlace = interlace;
+
 	return 0;
 }
 
@@ -213,8 +199,12 @@ static void armada_drm_primary_plane_atomic_update(struct drm_plane *plane,
 	    old_state->src.y1 != state->src.y1 ||
 	    old_state->fb != state->fb ||
 	    state->crtc->state->mode_changed) {
-		idx += armada_drm_crtc_calc_fb(state, regs + idx,
-					       dcrtc->interlaced);
+		armada_reg_queue_set(regs, idx, armada_addr(state, 0, 0),
+				     LCD_CFG_GRA_START_ADDR0);
+		armada_reg_queue_set(regs, idx, armada_addr(state, 1, 0),
+				     LCD_CFG_GRA_START_ADDR1);
+		armada_reg_queue_mod(regs, idx, armada_pitch(state, 0), 0xffff,
+				     LCD_CFG_GRA_PITCH);
 	}
 	if (old_state->fb != state->fb ||
 	    state->crtc->state->mode_changed) {
@@ -224,7 +214,7 @@ static void armada_drm_primary_plane_atomic_update(struct drm_plane *plane,
 			cfg |= CFG_PALETTE_ENA;
 		if (state->visible)
 			cfg |= CFG_GRA_ENA;
-		if (dcrtc->interlaced)
+		if (to_armada_plane_state(state)->interlace)
 			cfg |= CFG_GRA_FTOGGLE;
 		cfg_mask = CFG_GRAFORMAT |
 			   CFG_GRA_MOD(CFG_SWAPRB | CFG_SWAPUV |
diff --git a/drivers/gpu/drm/armada/armada_plane.h b/drivers/gpu/drm/armada/armada_plane.h
index 396c45a4ea5e..2707ec781941 100644
--- a/drivers/gpu/drm/armada/armada_plane.h
+++ b/drivers/gpu/drm/armada/armada_plane.h
@@ -6,6 +6,9 @@ struct armada_plane_state {
 	u32 src_hw;
 	u32 dst_yx;
 	u32 dst_hw;
+	u32 addrs[2][3];
+	u16 pitches[3];
+	bool interlace;
 };
 
 #define to_armada_plane_state(st) \
@@ -13,6 +16,8 @@ struct armada_plane_state {
 #define armada_src_hw(state) to_armada_plane_state(state)->src_hw
 #define armada_dst_yx(state) to_armada_plane_state(state)->dst_yx
 #define armada_dst_hw(state) to_armada_plane_state(state)->dst_hw
+#define armada_addr(state, f, p) to_armada_plane_state(state)->addrs[f][p]
+#define armada_pitch(state, n) to_armada_plane_state(state)->pitches[n]
 
 void armada_drm_plane_calc(struct drm_plane_state *state, u32 addrs[2][3],
 	u16 pitches[3], bool interlaced);
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 07/18] drm/armada: add support for setting gamma
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (5 preceding siblings ...)
  2019-06-13 15:02 ` [PATCH 06/18] drm/armada: move plane address and pitch calculation to atomic_check Russell King
@ 2019-06-13 15:02 ` Russell King
  2019-06-13 15:02 ` [PATCH 08/18] drm/armada: add comments about HWC32 cursor colour format Russell King
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:02 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Add support for setting gamma through both the legacy interfaces and
the atomic interfaces.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_crtc.c  | 63 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/armada/armada_hw.h    |  4 +++
 drivers/gpu/drm/armada/armada_plane.c |  2 +-
 3 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 09bade15f51c..5991feb1bcc9 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -130,6 +130,44 @@ static void armada_drm_crtc_queue_state_event(struct drm_crtc *crtc)
 	}
 }
 
+static void armada_drm_update_gamma(struct drm_crtc *crtc)
+{
+	struct drm_property_blob *blob = crtc->state->gamma_lut;
+	void __iomem *base = drm_to_armada_crtc(crtc)->base;
+	int i;
+
+	if (blob) {
+		struct drm_color_lut *lut = blob->data;
+
+		armada_updatel(CFG_CSB_256x8, CFG_CSB_256x8 | CFG_PDWN256x8,
+			       base + LCD_SPU_SRAM_PARA1);
+
+		for (i = 0; i < 256; i++) {
+			writel_relaxed(drm_color_lut_extract(lut[i].red, 8),
+				       base + LCD_SPU_SRAM_WRDAT);
+			writel_relaxed(i | SRAM_WRITE | SRAM_GAMMA_YR,
+				       base + LCD_SPU_SRAM_CTRL);
+			readl_relaxed(base + LCD_SPU_HWC_OVSA_HPXL_VLN);
+			writel_relaxed(drm_color_lut_extract(lut[i].green, 8),
+				       base + LCD_SPU_SRAM_WRDAT);
+			writel_relaxed(i | SRAM_WRITE | SRAM_GAMMA_UG,
+				       base + LCD_SPU_SRAM_CTRL);
+			readl_relaxed(base + LCD_SPU_HWC_OVSA_HPXL_VLN);
+			writel_relaxed(drm_color_lut_extract(lut[i].blue, 8),
+				       base + LCD_SPU_SRAM_WRDAT);
+			writel_relaxed(i | SRAM_WRITE | SRAM_GAMMA_VB,
+				       base + LCD_SPU_SRAM_CTRL);
+			readl_relaxed(base + LCD_SPU_HWC_OVSA_HPXL_VLN);
+		}
+		armada_updatel(CFG_GAMMA_ENA, CFG_GAMMA_ENA,
+			       base + LCD_SPU_DMA_CTRL0);
+	} else {
+		armada_updatel(0, CFG_GAMMA_ENA, base + LCD_SPU_DMA_CTRL0);
+		armada_updatel(CFG_PDWN256x8, CFG_CSB_256x8 | CFG_PDWN256x8,
+			       base + LCD_SPU_SRAM_PARA1);
+	}
+}
+
 /* The mode_config.mutex will be held for this call */
 static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
 	const struct drm_display_mode *mode, struct drm_display_mode *adj)
@@ -338,6 +376,20 @@ static void armada_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
 	spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
 }
 
+static int armada_drm_crtc_atomic_check(struct drm_crtc *crtc,
+					struct drm_crtc_state *state)
+{
+	DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
+
+	if (state->gamma_lut && drm_color_lut_size(state->gamma_lut) != 256)
+		return -EINVAL;
+
+	if (state->color_mgmt_changed)
+		state->planes_changed = true;
+
+	return 0;
+}
+
 static void armada_drm_crtc_atomic_begin(struct drm_crtc *crtc,
 					 struct drm_crtc_state *old_crtc_state)
 {
@@ -345,6 +397,9 @@ static void armada_drm_crtc_atomic_begin(struct drm_crtc *crtc,
 
 	DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
 
+	if (crtc->state->color_mgmt_changed)
+		armada_drm_update_gamma(crtc);
+
 	dcrtc->regs_idx = 0;
 	dcrtc->regs = dcrtc->atomic_regs;
 }
@@ -439,6 +494,7 @@ static void armada_drm_crtc_atomic_enable(struct drm_crtc *crtc,
 static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = {
 	.mode_fixup	= armada_drm_crtc_mode_fixup,
 	.mode_set_nofb	= armada_drm_crtc_mode_set_nofb,
+	.atomic_check	= armada_drm_crtc_atomic_check,
 	.atomic_begin	= armada_drm_crtc_atomic_begin,
 	.atomic_flush	= armada_drm_crtc_atomic_flush,
 	.atomic_disable	= armada_drm_crtc_atomic_disable,
@@ -702,6 +758,7 @@ static const struct drm_crtc_funcs armada_crtc_funcs = {
 	.cursor_set	= armada_drm_crtc_cursor_set,
 	.cursor_move	= armada_drm_crtc_cursor_move,
 	.destroy	= armada_drm_crtc_destroy,
+	.gamma_set	= drm_atomic_helper_legacy_gamma_set,
 	.set_config	= drm_atomic_helper_set_config,
 	.page_flip	= drm_atomic_helper_page_flip,
 	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
@@ -793,6 +850,12 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
 
 	drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs);
 
+	ret = drm_mode_crtc_set_gamma_size(&dcrtc->crtc, 256);
+	if (ret)
+		return ret;
+
+	drm_crtc_enable_color_mgmt(&dcrtc->crtc, 0, false, 256);
+
 	return armada_overlay_plane_create(drm, 1 << dcrtc->num);
 
 err_crtc_init:
diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h
index 345dc4d0851e..babfca71c4db 100644
--- a/drivers/gpu/drm/armada/armada_hw.h
+++ b/drivers/gpu/drm/armada/armada_hw.h
@@ -169,6 +169,10 @@ enum {
 	SRAM_READ	= 0 << 14,
 	SRAM_WRITE	= 2 << 14,
 	SRAM_INIT	= 3 << 14,
+	SRAM_GAMMA_YR	= 0x0 << 8,
+	SRAM_GAMMA_UG	= 0x1 << 8,
+	SRAM_GAMMA_VB	= 0x2 << 8,
+	SRAM_PALETTE	= 0x3 << 8,
 	SRAM_HWC32_RAM1	= 0xc << 8,
 	SRAM_HWC32_RAM2	= 0xd << 8,
 	SRAM_HWC32_RAMR	= SRAM_HWC32_RAM1,
diff --git a/drivers/gpu/drm/armada/armada_plane.c b/drivers/gpu/drm/armada/armada_plane.c
index 45092fc3598e..dbd4d52e8a32 100644
--- a/drivers/gpu/drm/armada/armada_plane.c
+++ b/drivers/gpu/drm/armada/armada_plane.c
@@ -265,7 +265,7 @@ static void armada_drm_primary_plane_atomic_disable(struct drm_plane *plane,
 	/* Disable plane and power down most RAMs and FIFOs */
 	armada_reg_queue_mod(regs, idx, 0, CFG_GRA_ENA, LCD_SPU_DMA_CTRL0);
 	armada_reg_queue_mod(regs, idx, CFG_PDWN256x32 | CFG_PDWN256x24 |
-			     CFG_PDWN256x8 | CFG_PDWN32x32 | CFG_PDWN64x66,
+			     CFG_PDWN32x32 | CFG_PDWN64x66,
 			     0, LCD_SPU_SRAM_PARA1);
 
 	dcrtc->regs_idx += idx;
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 08/18] drm/armada: add comments about HWC32 cursor colour format
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (6 preceding siblings ...)
  2019-06-13 15:02 ` [PATCH 07/18] drm/armada: add support for setting gamma Russell King
@ 2019-06-13 15:02 ` Russell King
  2019-06-13 15:02 ` [PATCH 09/18] drm/armada: add drm_mode_set_crtcinfo() mode fixup Russell King
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:02 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Add some comments about the format of the HWC32 cursor colour format.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_crtc.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 5991feb1bcc9..e81e57823b66 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -515,6 +515,13 @@ static void armada_load_cursor_argb(void __iomem *base, uint32_t *pix,
 		for (x = 0; x < width; x++, p++) {
 			uint32_t val = *p;
 
+			/*
+			 * In "ARGB888" (HWC32) mode, writing to the SRAM
+			 * requires these bits to contain:
+			 * 31:24 = alpha 23:16 = blue 15:8 = green 7:0 = red
+			 * So, it's actually ABGR8888.  This is independent
+			 * of the SWAPRB bits in DMA control register 0.
+			 */
 			val = (val & 0xff00ff00) |
 			      (val & 0x000000ff) << 16 |
 			      (val & 0x00ff0000) >> 16;
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 09/18] drm/armada: add drm_mode_set_crtcinfo() mode fixup
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (7 preceding siblings ...)
  2019-06-13 15:02 ` [PATCH 08/18] drm/armada: add comments about HWC32 cursor colour format Russell King
@ 2019-06-13 15:02 ` Russell King
  2019-06-13 15:02 ` [PATCH 10/18] drm/armada: add and use definitions for RDREG4F Russell King
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:02 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Add a drm_mode_set_crtcinfo() call in our CRTC's mode_fixup callback
to ensure that any adjustments to the mode made by connectors etc are
properly accounted for by the CRTC.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_crtc.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index e81e57823b66..d802a6bc2d9f 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -180,6 +180,13 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
 	    adj->flags & DRM_MODE_FLAG_INTERLACE)
 		return false;
 
+	/*
+	 * Set CRTC modesetting parameters for the adjusted mode.  This is
+	 * applied after the connectors, bridges, and encoders have fixed up
+	 * this mode, as described above drm_atomic_helper_check_modeset().
+	 */
+	drm_mode_set_crtcinfo(adj, CRTC_INTERLACE_HALVE_V);
+
 	/* Check whether the display mode is possible */
 	ret = dcrtc->variant->compute_clock(dcrtc, adj, NULL);
 	if (ret)
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 10/18] drm/armada: add and use definitions for RDREG4F
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (8 preceding siblings ...)
  2019-06-13 15:02 ` [PATCH 09/18] drm/armada: add drm_mode_set_crtcinfo() mode fixup Russell King
@ 2019-06-13 15:02 ` Russell King
  2019-06-13 15:02 ` [PATCH 11/18] drm/armada: add drm_atomic_helper_shutdown() call in tear-down Russell King
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:02 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Add and use bit definitions for RDREG4F on Dove Armada 510.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_510.c |  9 +++++++--
 drivers/gpu/drm/armada/armada_hw.h  | 10 ++++++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_510.c b/drivers/gpu/drm/armada/armada_510.c
index 0e91d27921bd..370c422f64e3 100644
--- a/drivers/gpu/drm/armada/armada_510.c
+++ b/drivers/gpu/drm/armada/armada_510.c
@@ -24,8 +24,13 @@ static int armada510_crtc_init(struct armada_crtc *dcrtc, struct device *dev)
 
 	dcrtc->extclk[0] = clk;
 
-	/* Lower the watermark so to eliminate jitter at higher bandwidths */
-	armada_updatel(0x20, (1 << 11) | 0xff, dcrtc->base + LCD_CFG_RDREG4F);
+	/*
+	 * Lower the watermark so to eliminate jitter at higher bandwidths.
+	 * Disable SRAM read wait state to avoid system hang with external
+	 * clock.
+	 */
+	armada_updatel(CFG_DMA_WM(0x20), CFG_SRAM_WAIT | CFG_DMA_WM_MASK,
+		       dcrtc->base + LCD_CFG_RDREG4F);
 
 	/* Initialise SPU register */
 	writel_relaxed(ADV_HWC32ENABLE | ADV_HWC32ARGB | ADV_HWC32BLEND,
diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h
index babfca71c4db..5b1af0cc9f50 100644
--- a/drivers/gpu/drm/armada/armada_hw.h
+++ b/drivers/gpu/drm/armada/armada_hw.h
@@ -88,6 +88,16 @@ enum {
 	ADV_VSYNC_H_OFF	= 0xfff << 0,
 };
 
+/* LCD_CFG_RDREG4F - Armada 510 only */
+enum {
+	CFG_SRAM_WAIT	= BIT(11),
+	CFG_SMPN_FASTTX	= BIT(10),
+	CFG_DMA_ARB	= BIT(9),
+	CFG_DMA_WM_EN	= BIT(8),
+	CFG_DMA_WM_MASK	= 0xff,
+#define CFG_DMA_WM(x)	((x) & CFG_DMA_WM_MASK)
+};
+
 enum {
 	CFG_565		= 0,
 	CFG_1555	= 1,
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 11/18] drm/armada: add drm_atomic_helper_shutdown() call in tear-down
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (9 preceding siblings ...)
  2019-06-13 15:02 ` [PATCH 10/18] drm/armada: add and use definitions for RDREG4F Russell King
@ 2019-06-13 15:02 ` Russell King
  2019-06-13 15:02 ` [PATCH 12/18] drm/armada: add CRTC mode validation Russell King
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:02 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Ensure that the hardware is disabled prior to tearing down the modeset
support.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index e660c5ca52ae..e524bfff1c49 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -171,6 +171,8 @@ static void armada_drm_unbind(struct device *dev)
 
 	drm_dev_unregister(&priv->drm);
 
+	drm_atomic_helper_shutdown(&priv->drm);
+
 	component_unbind_all(dev, &priv->drm);
 
 	drm_mode_config_cleanup(&priv->drm);
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 12/18] drm/armada: add CRTC mode validation
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (10 preceding siblings ...)
  2019-06-13 15:02 ` [PATCH 11/18] drm/armada: add drm_atomic_helper_shutdown() call in tear-down Russell King
@ 2019-06-13 15:02 ` Russell King
  2019-06-13 15:02 ` [PATCH 13/18] drm/armada: improve Dove clock selection Russell King
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:02 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Add CRTC mode validation to reject modes that the CRTC does not support.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_crtc.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index d802a6bc2d9f..edce74f60198 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -168,6 +168,25 @@ static void armada_drm_update_gamma(struct drm_crtc *crtc)
 	}
 }
 
+static enum drm_mode_status armada_drm_crtc_mode_valid(struct drm_crtc *crtc,
+	const struct drm_display_mode *mode)
+{
+	if (mode->vscan > 1)
+		return MODE_NO_VSCAN;
+
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		return MODE_NO_DBLESCAN;
+
+	if (mode->flags & DRM_MODE_FLAG_HSKEW)
+		return MODE_H_ILLEGAL;
+
+	if (mode->flags & (DRM_MODE_FLAG_BCAST | DRM_MODE_FLAG_PIXMUX |
+			   DRM_MODE_FLAG_CLKDIV2))
+		return MODE_BAD;
+
+	return MODE_OK;
+}
+
 /* The mode_config.mutex will be held for this call */
 static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
 	const struct drm_display_mode *mode, struct drm_display_mode *adj)
@@ -499,6 +518,7 @@ static void armada_drm_crtc_atomic_enable(struct drm_crtc *crtc,
 }
 
 static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = {
+	.mode_valid	= armada_drm_crtc_mode_valid,
 	.mode_fixup	= armada_drm_crtc_mode_fixup,
 	.mode_set_nofb	= armada_drm_crtc_mode_set_nofb,
 	.atomic_check	= armada_drm_crtc_atomic_check,
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 13/18] drm/armada: improve Dove clock selection
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (11 preceding siblings ...)
  2019-06-13 15:02 ` [PATCH 12/18] drm/armada: add CRTC mode validation Russell King
@ 2019-06-13 15:02 ` Russell King
  2019-06-13 15:02 ` [PATCH 14/18] drm/armada: use mode_valid to validate the adjusted mode Russell King
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:02 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Improve the Dove (Armada 510) LCD clock selection and divider
calculation, limiting to the valid divisor values, and reporting an
error if the clock is not achievable within the bounds of HDMI
clocking requirements.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_510.c  | 121 +++++++++++++++++++++++++----------
 drivers/gpu/drm/armada/armada_crtc.c |  78 +++++++++++++++++++++-
 drivers/gpu/drm/armada/armada_crtc.h |  21 +++++-
 3 files changed, 183 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_510.c b/drivers/gpu/drm/armada/armada_510.c
index 370c422f64e3..6f8ad8fb19f1 100644
--- a/drivers/gpu/drm/armada/armada_510.c
+++ b/drivers/gpu/drm/armada/armada_510.c
@@ -14,15 +14,54 @@
 #include "armada_drm.h"
 #include "armada_hw.h"
 
+struct armada510_variant_data {
+	struct clk *clks[4];
+	struct clk *sel_clk;
+};
+
 static int armada510_crtc_init(struct armada_crtc *dcrtc, struct device *dev)
 {
+	struct armada510_variant_data *v;
 	struct clk *clk;
-
-	clk = devm_clk_get(dev, "ext_ref_clk1");
-	if (IS_ERR(clk))
-		return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER : PTR_ERR(clk);
-
-	dcrtc->extclk[0] = clk;
+	int idx;
+
+	v = devm_kzalloc(dev, sizeof(*v), GFP_KERNEL);
+	if (!v)
+		return -ENOMEM;
+
+	dcrtc->variant_data = v;
+
+	if (dev->of_node) {
+		struct property *prop;
+		const char *s;
+
+		of_property_for_each_string(dev->of_node, "clock-names", prop,
+					    s) {
+			if (!strcmp(s, "ext_ref_clk0"))
+				idx = 0;
+			else if (!strcmp(s, "ext_ref_clk1"))
+				idx = 1;
+			else if (!strcmp(s, "plldivider"))
+				idx = 2;
+			else if (!strcmp(s, "axibus"))
+				idx = 3;
+			else
+				continue;
+
+			clk = devm_clk_get(dev, s);
+			if (IS_ERR(clk))
+				return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER :
+					PTR_ERR(clk);
+			v->clks[idx] = clk;
+		}
+	} else {
+		clk = devm_clk_get(dev, "ext_ref_clk1");
+		if (IS_ERR(clk))
+			return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER :
+				PTR_ERR(clk);
+
+		v->clks[1] = clk;
+	}
 
 	/*
 	 * Lower the watermark so to eliminate jitter at higher bandwidths.
@@ -39,65 +78,77 @@ static int armada510_crtc_init(struct armada_crtc *dcrtc, struct device *dev)
 	return 0;
 }
 
+static const u32 armada510_clk_sels[] = {
+	SCLK_510_EXTCLK0,
+	SCLK_510_EXTCLK1,
+	SCLK_510_PLL,
+	SCLK_510_AXI,
+};
+
+static const struct armada_clocking_params armada510_clocking = {
+	/* HDMI requires -0.6%..+0.5% */
+	.permillage_min = 994,
+	.permillage_max = 1005,
+	.settable = BIT(0) | BIT(1),
+	.div_max = SCLK_510_INT_DIV_MASK,
+};
+
 /*
  * Armada510 specific SCLK register selection.
  * This gets called with sclk = NULL to test whether the mode is
  * supportable, and again with sclk != NULL to set the clocks up for
  * that.  The former can return an error, but the latter is expected
  * not to.
- *
- * We currently are pretty rudimentary here, always selecting
- * EXT_REF_CLK_1 for LCD0 and erroring LCD1.  This needs improvement!
  */
 static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
 	const struct drm_display_mode *mode, uint32_t *sclk)
 {
-	struct clk *clk = dcrtc->extclk[0];
-	int ret;
+	struct armada510_variant_data *v = dcrtc->variant_data;
+	unsigned long desired_khz = mode->crtc_clock;
+	struct armada_clk_result res;
+	int ret, idx;
 
-	if (dcrtc->num == 1)
-		return -EINVAL;
+	idx = armada_crtc_select_clock(dcrtc, &res, &armada510_clocking,
+				       v->clks, ARRAY_SIZE(v->clks),
+				       desired_khz);
+	if (idx < 0)
+		return idx;
 
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
-
-	if (dcrtc->clk != clk) {
-		ret = clk_prepare_enable(clk);
-		if (ret)
-			return ret;
-		dcrtc->clk = clk;
-	}
+	ret = clk_prepare_enable(res.clk);
+	if (ret)
+		return ret;
 
 	if (sclk) {
-		uint32_t rate, ref, div;
+		clk_set_rate(res.clk, res.desired_clk_hz);
 
-		rate = mode->clock * 1000;
-		ref = clk_round_rate(clk, rate);
-		div = DIV_ROUND_UP(ref, rate);
-		if (div < 1)
-			div = 1;
+		*sclk = res.div | armada510_clk_sels[idx];
 
-		clk_set_rate(clk, ref);
-		*sclk = div | SCLK_510_EXTCLK1;
+		/* We are now using this clock */
+		v->sel_clk = res.clk;
+		swap(dcrtc->clk, res.clk);
 	}
 
+	clk_disable_unprepare(res.clk);
+
 	return 0;
 }
 
 static void armada510_crtc_disable(struct armada_crtc *dcrtc)
 {
-	if (!IS_ERR(dcrtc->clk)) {
+	if (dcrtc->clk) {
 		clk_disable_unprepare(dcrtc->clk);
-		dcrtc->clk = ERR_PTR(-EINVAL);
+		dcrtc->clk = NULL;
 	}
 }
 
 static void armada510_crtc_enable(struct armada_crtc *dcrtc,
 	const struct drm_display_mode *mode)
 {
-	if (IS_ERR(dcrtc->clk)) {
-		dcrtc->clk = dcrtc->extclk[0];
-		WARN_ON(clk_prepare_enable(dcrtc->clk));
+	struct armada510_variant_data *v = dcrtc->variant_data;
+
+	if (!dcrtc->clk && v->sel_clk) {
+		if (!WARN_ON(clk_prepare_enable(v->sel_clk)))
+			dcrtc->clk = v->sel_clk;
 	}
 }
 
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index edce74f60198..949acc82406b 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -801,6 +801,83 @@ static const struct drm_crtc_funcs armada_crtc_funcs = {
 	.disable_vblank	= armada_drm_crtc_disable_vblank,
 };
 
+int armada_crtc_select_clock(struct armada_crtc *dcrtc,
+			     struct armada_clk_result *res,
+			     const struct armada_clocking_params *params,
+			     struct clk *clks[], size_t num_clks,
+			     unsigned long desired_khz)
+{
+	unsigned long desired_hz = desired_khz * 1000;
+	unsigned long desired_clk_hz;	// requested clk input
+	unsigned long real_clk_hz;	// actual clk input
+	unsigned long real_hz;		// actual pixel clk
+	unsigned long permillage;
+	struct clk *clk;
+	u32 div;
+	int i;
+
+	DRM_DEBUG_KMS("[CRTC:%u:%s] desired clock=%luHz\n",
+		      dcrtc->crtc.base.id, dcrtc->crtc.name, desired_hz);
+
+	for (i = 0; i < num_clks; i++) {
+		clk = clks[i];
+		if (!clk)
+			continue;
+
+		if (params->settable & BIT(i)) {
+			real_clk_hz = clk_round_rate(clk, desired_hz);
+			desired_clk_hz = desired_hz;
+		} else {
+			real_clk_hz = clk_get_rate(clk);
+			desired_clk_hz = real_clk_hz;
+		}
+
+		/* If the clock can do exactly the desired rate, we're done */
+		if (real_clk_hz == desired_hz) {
+			real_hz = real_clk_hz;
+			div = 1;
+			break;
+		}
+
+		/* Calculate the divider - if invalid, we can't do this rate */
+		div = DIV_ROUND_CLOSEST(real_clk_hz, desired_hz);
+		if (div == 0 || div > params->div_max)
+			continue;
+
+		/* Calculate the actual rate - HDMI requires -0.6%..+0.5% */
+		real_hz = DIV_ROUND_CLOSEST(real_clk_hz, div);
+
+		DRM_DEBUG_KMS("[CRTC:%u:%s] clk=%u %luHz div=%u real=%luHz\n",
+			dcrtc->crtc.base.id, dcrtc->crtc.name,
+			i, real_clk_hz, div, real_hz);
+
+		/* Avoid repeated division */
+		if (real_hz < desired_hz) {
+			permillage = real_hz / desired_khz;
+			if (permillage < params->permillage_min)
+				continue;
+		} else {
+			permillage = DIV_ROUND_UP(real_hz, desired_khz);
+			if (permillage > params->permillage_max)
+				continue;
+		}
+		break;
+	}
+
+	if (i == 4)
+		return -ERANGE;
+
+	DRM_DEBUG_KMS("[CRTC:%u:%s] selected clk=%u %luHz div=%u real=%luHz\n",
+		dcrtc->crtc.base.id, dcrtc->crtc.name,
+		i, real_clk_hz, div, real_hz);
+
+	res->desired_clk_hz = desired_clk_hz;
+	res->clk = clk;
+	res->div = div;
+
+	return i;
+}
+
 static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
 	struct resource *res, int irq, const struct armada_variant *variant,
 	struct device_node *port)
@@ -827,7 +904,6 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
 	dcrtc->variant = variant;
 	dcrtc->base = base;
 	dcrtc->num = drm->mode_config.num_crtc;
-	dcrtc->clk = ERR_PTR(-EINVAL);
 	dcrtc->cfg_dumb_ctrl = DUMB24_RGB888_0;
 	dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;
 	spin_lock_init(&dcrtc->irq_lock);
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
index 08761ff01739..fb4aa48da60c 100644
--- a/drivers/gpu/drm/armada/armada_crtc.h
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -39,10 +39,10 @@ struct armada_variant;
 struct armada_crtc {
 	struct drm_crtc		crtc;
 	const struct armada_variant *variant;
+	void			*variant_data;
 	unsigned		num;
 	void __iomem		*base;
 	struct clk		*clk;
-	struct clk		*extclk[2];
 	struct {
 		uint32_t	spu_v_h_total;
 		uint32_t	spu_v_porch;
@@ -75,6 +75,25 @@ struct armada_crtc {
 
 void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
 
+struct armada_clocking_params {
+	unsigned long permillage_min;
+	unsigned long permillage_max;
+	u32 settable;
+	u32 div_max;
+};
+
+struct armada_clk_result {
+	unsigned long desired_clk_hz;
+	struct clk *clk;
+	u32 div;
+};
+
+int armada_crtc_select_clock(struct armada_crtc *dcrtc,
+			     struct armada_clk_result *res,
+			     const struct armada_clocking_params *params,
+			     struct clk *clks[], size_t num_clks,
+			     unsigned long desired_khz);
+
 extern struct platform_driver armada_lcd_platform_driver;
 
 #endif
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 14/18] drm/armada: use mode_valid to validate the adjusted mode
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (12 preceding siblings ...)
  2019-06-13 15:02 ` [PATCH 13/18] drm/armada: improve Dove clock selection Russell King
@ 2019-06-13 15:02 ` Russell King
  2019-06-13 15:02 ` [PATCH 15/18] drm/armada: redo CRTC debugfs files Russell King
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:02 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Validate the adjusted mode in the CRTC mode_fixup() call to ensure that
any encoder or bridge doesn't supply us with a mode we can't support.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_crtc.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 949acc82406b..ecce7efb271d 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -171,6 +171,8 @@ static void armada_drm_update_gamma(struct drm_crtc *crtc)
 static enum drm_mode_status armada_drm_crtc_mode_valid(struct drm_crtc *crtc,
 	const struct drm_display_mode *mode)
 {
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+
 	if (mode->vscan > 1)
 		return MODE_NO_VSCAN;
 
@@ -180,6 +182,11 @@ static enum drm_mode_status armada_drm_crtc_mode_valid(struct drm_crtc *crtc,
 	if (mode->flags & DRM_MODE_FLAG_HSKEW)
 		return MODE_H_ILLEGAL;
 
+	/* We can't do interlaced modes if we don't have the SPU_ADV_REG */
+	if (!dcrtc->variant->has_spu_adv_reg &&
+	    mode->flags & DRM_MODE_FLAG_INTERLACE)
+		return MODE_NO_INTERLACE;
+
 	if (mode->flags & (DRM_MODE_FLAG_BCAST | DRM_MODE_FLAG_PIXMUX |
 			   DRM_MODE_FLAG_CLKDIV2))
 		return MODE_BAD;
@@ -194,11 +201,6 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
 	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
 	int ret;
 
-	/* We can't do interlaced modes if we don't have the SPU_ADV_REG */
-	if (!dcrtc->variant->has_spu_adv_reg &&
-	    adj->flags & DRM_MODE_FLAG_INTERLACE)
-		return false;
-
 	/*
 	 * Set CRTC modesetting parameters for the adjusted mode.  This is
 	 * applied after the connectors, bridges, and encoders have fixed up
@@ -206,6 +208,13 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
 	 */
 	drm_mode_set_crtcinfo(adj, CRTC_INTERLACE_HALVE_V);
 
+	/*
+	 * Validate the adjusted mode in case an encoder/bridge has set
+	 * something we don't support.
+	 */
+	if (armada_drm_crtc_mode_valid(crtc, adj) != MODE_OK)
+		return false;
+
 	/* Check whether the display mode is possible */
 	ret = dcrtc->variant->compute_clock(dcrtc, adj, NULL);
 	if (ret)
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 15/18] drm/armada: redo CRTC debugfs files
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (13 preceding siblings ...)
  2019-06-13 15:02 ` [PATCH 14/18] drm/armada: use mode_valid to validate the adjusted mode Russell King
@ 2019-06-13 15:02 ` Russell King
  2019-06-13 15:03 ` [PATCH 16/18] drm/armada: replace the simple-framebuffer Russell King
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:02 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Move the CRTC debugfs files into the CRTC specific directory.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_crtc.c    |  7 +++
 drivers/gpu/drm/armada/armada_debugfs.c | 98 +++++++++++++--------------------
 drivers/gpu/drm/armada/armada_drm.h     |  1 +
 3 files changed, 46 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index ecce7efb271d..bea78f39785a 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -774,6 +774,12 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
 	kfree(dcrtc);
 }
 
+static int armada_drm_crtc_late_register(struct drm_crtc *crtc)
+{
+	armada_drm_crtc_debugfs_init(drm_to_armada_crtc(crtc));
+	return 0;
+}
+
 /* These are called under the vbl_lock. */
 static int armada_drm_crtc_enable_vblank(struct drm_crtc *crtc)
 {
@@ -806,6 +812,7 @@ static const struct drm_crtc_funcs armada_crtc_funcs = {
 	.page_flip	= drm_atomic_helper_page_flip,
 	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+	.late_register	= armada_drm_crtc_late_register,
 	.enable_vblank	= armada_drm_crtc_enable_vblank,
 	.disable_vblank	= armada_drm_crtc_disable_vblank,
 };
diff --git a/drivers/gpu/drm/armada/armada_debugfs.c b/drivers/gpu/drm/armada/armada_debugfs.c
index 6758c3a83de2..4dcce002ea2a 100644
--- a/drivers/gpu/drm/armada/armada_debugfs.c
+++ b/drivers/gpu/drm/armada/armada_debugfs.c
@@ -28,50 +28,33 @@ static int armada_debugfs_gem_linear_show(struct seq_file *m, void *data)
 	return 0;
 }
 
-static int armada_debugfs_reg_show(struct seq_file *m, void *data)
+static int armada_debugfs_crtc_reg_show(struct seq_file *m, void *data)
 {
-	struct drm_device *dev = m->private;
-	struct armada_private *priv = dev->dev_private;
-	int n, i;
-
-	if (priv) {
-		for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
-			struct armada_crtc *dcrtc = priv->dcrtc[n];
-			if (!dcrtc)
-				continue;
-
-			for (i = 0x84; i <= 0x1c4; i += 4) {
-				uint32_t v = readl_relaxed(dcrtc->base + i);
-				seq_printf(m, "%u: 0x%04x: 0x%08x\n", n, i, v);
-			}
-		}
+	struct armada_crtc *dcrtc = m->private;
+	int i;
+
+	for (i = 0x84; i <= 0x1c4; i += 4) {
+		u32 v = readl_relaxed(dcrtc->base + i);
+		seq_printf(m, "0x%04x: 0x%08x\n", i, v);
 	}
 
 	return 0;
 }
 
-static int armada_debugfs_reg_r_open(struct inode *inode, struct file *file)
+static int armada_debugfs_crtc_reg_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, armada_debugfs_reg_show, inode->i_private);
+	return single_open(file, armada_debugfs_crtc_reg_show,
+			   inode->i_private);
 }
 
-static const struct file_operations fops_reg_r = {
-	.owner = THIS_MODULE,
-	.open = armada_debugfs_reg_r_open,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static int armada_debugfs_write(struct file *file, const char __user *ptr,
-	size_t len, loff_t *off)
+static int armada_debugfs_crtc_reg_write(struct file *file,
+	const char __user *ptr, size_t len, loff_t *off)
 {
-	struct drm_device *dev = file->private_data;
-	struct armada_private *priv = dev->dev_private;
-	struct armada_crtc *dcrtc = priv->dcrtc[0];
-	char buf[32], *p;
-	uint32_t reg, val;
+	struct armada_crtc *dcrtc;
+	unsigned long reg, mask, val;
+	char buf[32];
 	int ret;
+	u32 v;
 
 	if (*off != 0)
 		return 0;
@@ -84,24 +67,35 @@ static int armada_debugfs_write(struct file *file, const char __user *ptr,
 		return ret;
 	buf[len] = '\0';
 
-	reg = simple_strtoul(buf, &p, 16);
-	if (!isspace(*p))
+	if (sscanf(buf, "%lx %lx %lx", &reg, &mask, &val) != 3)
 		return -EINVAL;
-	val = simple_strtoul(p + 1, NULL, 16);
+	if (reg < 0x84 || reg > 0x1c4 || reg & 3)
+		return -ERANGE;
 
-	if (reg >= 0x84 && reg <= 0x1c4)
-		writel(val, dcrtc->base + reg);
+	dcrtc = ((struct seq_file *)file->private_data)->private;
+	v = readl(dcrtc->base + reg);
+	v &= ~mask;
+	v |= val & mask;
+	writel(v, dcrtc->base + reg);
 
 	return len;
 }
 
-static const struct file_operations fops_reg_w = {
+static const struct file_operations armada_debugfs_crtc_reg_fops = {
 	.owner = THIS_MODULE,
-	.open = simple_open,
-	.write = armada_debugfs_write,
-	.llseek = noop_llseek,
+	.open = armada_debugfs_crtc_reg_open,
+	.read = seq_read,
+	.write = armada_debugfs_crtc_reg_write,
+	.llseek = seq_lseek,
+	.release = single_release,
 };
 
+void armada_drm_crtc_debugfs_init(struct armada_crtc *dcrtc)
+{
+	debugfs_create_file("armada-regs", 0600, dcrtc->crtc.debugfs_entry,
+			    dcrtc, &armada_debugfs_crtc_reg_fops);
+}
+
 static struct drm_info_list armada_debugfs_list[] = {
 	{ "gem_linear", armada_debugfs_gem_linear_show, 0 },
 };
@@ -109,24 +103,8 @@ static struct drm_info_list armada_debugfs_list[] = {
 
 int armada_drm_debugfs_init(struct drm_minor *minor)
 {
-	struct dentry *de;
-	int ret;
-
-	ret = drm_debugfs_create_files(armada_debugfs_list,
-				       ARMADA_DEBUGFS_ENTRIES,
-				       minor->debugfs_root, minor);
-	if (ret)
-		return ret;
-
-	de = debugfs_create_file("reg", S_IFREG | S_IRUSR,
-				 minor->debugfs_root, minor->dev, &fops_reg_r);
-	if (!de)
-		return -ENOMEM;
-
-	de = debugfs_create_file("reg_wr", S_IFREG | S_IWUSR,
-				 minor->debugfs_root, minor->dev, &fops_reg_w);
-	if (!de)
-		return -ENOMEM;
+	drm_debugfs_create_files(armada_debugfs_list, ARMADA_DEBUGFS_ENTRIES,
+				 minor->debugfs_root, minor);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index f09083ff15d3..b6307235f320 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -78,6 +78,7 @@ void armada_fbdev_fini(struct drm_device *);
 
 int armada_overlay_plane_create(struct drm_device *, unsigned long);
 
+void armada_drm_crtc_debugfs_init(struct armada_crtc *dcrtc);
 int armada_drm_debugfs_init(struct drm_minor *);
 
 #endif
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 16/18] drm/armada: replace the simple-framebuffer
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (14 preceding siblings ...)
  2019-06-13 15:02 ` [PATCH 15/18] drm/armada: redo CRTC debugfs files Russell King
@ 2019-06-13 15:03 ` Russell King
  2019-06-13 15:03 ` [PATCH 17/18] drm/armada: use for_each_endpoint_of_node() to walk crtc endpoints Russell King
  2019-06-13 15:03 ` [PATCH 18/18] drm/armada: no need to check parent of remote Russell King
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:03 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

From: Lubomir Rintel <lkundrak@v3.sk>

If there's a simple-framebuffer carried over from boot firmware, it's going
to stop working once we setup the LCDC for use via DRM. Kick it off from
the hardware.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_drv.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index e524bfff1c49..05fab5cb5c2d 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -100,6 +100,17 @@ static int armada_drm_bind(struct device *dev)
 		return ret;
 	}
 
+	/* Remove early framebuffers */
+	ret = drm_fb_helper_remove_conflicting_framebuffers(NULL,
+							    "armada-drm-fb",
+							    false);
+	if (ret) {
+		dev_err(dev, "[" DRM_NAME ":%s] can't kick out simple-fb: %d\n",
+			__func__, ret);
+		kfree(priv);
+		return ret;
+	}
+
 	priv->drm.dev_private = priv;
 
 	dev_set_drvdata(dev, &priv->drm);
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 17/18] drm/armada: use for_each_endpoint_of_node() to walk crtc endpoints
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (15 preceding siblings ...)
  2019-06-13 15:03 ` [PATCH 16/18] drm/armada: replace the simple-framebuffer Russell King
@ 2019-06-13 15:03 ` Russell King
  2019-06-13 15:03 ` [PATCH 18/18] drm/armada: no need to check parent of remote Russell King
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:03 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

Rather than having a nested set of for_each_child_of_node() walkers,
use the graph walker to iterate through the endpoints for CRTCs.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_drv.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 05fab5cb5c2d..1cfabcd6a629 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -204,11 +204,11 @@ static int compare_dev_name(struct device *dev, void *data)
 }
 
 static void armada_add_endpoints(struct device *dev,
-	struct component_match **match, struct device_node *port)
+	struct component_match **match, struct device_node *dev_node)
 {
 	struct device_node *ep, *remote;
 
-	for_each_child_of_node(port, ep) {
+	for_each_endpoint_of_node(dev_node, ep) {
 		remote = of_graph_get_remote_port_parent(ep);
 		if (!remote || !of_device_is_available(remote)) {
 			of_node_put(remote);
@@ -242,7 +242,6 @@ static int armada_drm_probe(struct platform_device *pdev)
 
 	if (dev->platform_data) {
 		char **devices = dev->platform_data;
-		struct device_node *port;
 		struct device *d;
 		int i;
 
@@ -258,10 +257,8 @@ static int armada_drm_probe(struct platform_device *pdev)
 		for (i = 0; devices[i]; i++) {
 			d = bus_find_device_by_name(&platform_bus_type, NULL,
 						    devices[i]);
-			if (d && d->of_node) {
-				for_each_child_of_node(d->of_node, port)
-					armada_add_endpoints(dev, &match, port);
-			}
+			if (d && d->of_node)
+				armada_add_endpoints(dev, &match, d->of_node);
 			put_device(d);
 		}
 	}
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 18/18] drm/armada: no need to check parent of remote
  2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
                   ` (16 preceding siblings ...)
  2019-06-13 15:03 ` [PATCH 17/18] drm/armada: use for_each_endpoint_of_node() to walk crtc endpoints Russell King
@ 2019-06-13 15:03 ` Russell King
  17 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2019-06-13 15:03 UTC (permalink / raw)
  To: dri-devel, linux-arm-kernel; +Cc: David Airlie, Daniel Vetter

There's no need to check the parent of the remote device to check
whether it is available or not, the remote is the device itself.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_drv.c | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 1cfabcd6a629..f1729398b1bd 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -210,17 +210,9 @@ static void armada_add_endpoints(struct device *dev,
 
 	for_each_endpoint_of_node(dev_node, ep) {
 		remote = of_graph_get_remote_port_parent(ep);
-		if (!remote || !of_device_is_available(remote)) {
-			of_node_put(remote);
-			continue;
-		} else if (!of_device_is_available(remote->parent)) {
-			dev_warn(dev, "parent device of %pOF is not available\n",
-				 remote);
-			of_node_put(remote);
-			continue;
-		}
-
-		drm_of_component_match_add(dev, match, compare_of, remote);
+		if (remote && of_device_is_available(remote))
+			drm_of_component_match_add(dev, match, compare_of,
+						   remote);
 		of_node_put(remote);
 	}
 }
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

end of thread, other threads:[~2019-06-13 15:08 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-13 15:01 [PATCH 00/18] Armada DRM updates Russell King - ARM Linux admin
2019-06-13 15:01 ` [PATCH 01/18] drm/armada: fix crtc interlace Russell King
2019-06-13 15:01 ` [PATCH 02/18] drm/armada: use __drm_atomic_helper_plane_reset in overlay reset Russell King
2019-06-13 15:01 ` [PATCH 03/18] drm/armada: add plane size/location accessors Russell King
2019-06-13 15:02 ` [PATCH 04/18] drm/armada: fix plane location and size for interlace Russell King
2019-06-13 15:02 ` [PATCH 05/18] drm/armada: add missing interlaced support for overlay frame Russell King
2019-06-13 15:02 ` [PATCH 06/18] drm/armada: move plane address and pitch calculation to atomic_check Russell King
2019-06-13 15:02 ` [PATCH 07/18] drm/armada: add support for setting gamma Russell King
2019-06-13 15:02 ` [PATCH 08/18] drm/armada: add comments about HWC32 cursor colour format Russell King
2019-06-13 15:02 ` [PATCH 09/18] drm/armada: add drm_mode_set_crtcinfo() mode fixup Russell King
2019-06-13 15:02 ` [PATCH 10/18] drm/armada: add and use definitions for RDREG4F Russell King
2019-06-13 15:02 ` [PATCH 11/18] drm/armada: add drm_atomic_helper_shutdown() call in tear-down Russell King
2019-06-13 15:02 ` [PATCH 12/18] drm/armada: add CRTC mode validation Russell King
2019-06-13 15:02 ` [PATCH 13/18] drm/armada: improve Dove clock selection Russell King
2019-06-13 15:02 ` [PATCH 14/18] drm/armada: use mode_valid to validate the adjusted mode Russell King
2019-06-13 15:02 ` [PATCH 15/18] drm/armada: redo CRTC debugfs files Russell King
2019-06-13 15:03 ` [PATCH 16/18] drm/armada: replace the simple-framebuffer Russell King
2019-06-13 15:03 ` [PATCH 17/18] drm/armada: use for_each_endpoint_of_node() to walk crtc endpoints Russell King
2019-06-13 15:03 ` [PATCH 18/18] drm/armada: no need to check parent of remote Russell King

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