All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maxime Ripard <maxime@cerno.tech>
To: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>,
	Eric Anholt <eric@anholt.net>
Cc: dri-devel@lists.freedesktop.org,
	linux-rpi-kernel@lists.infradead.org,
	bcm-kernel-feedback-list@broadcom.com,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org,
	Dave Stevenson <dave.stevenson@raspberrypi.com>,
	Tim Gover <tim.gover@raspberrypi.com>,
	Phil Elwell <phil@raspberrypi.com>,
	Maxime Ripard <maxime@cerno.tech>,
	Chanwoo Choi <cw00.choi@samsung.com>,
	Hoegeun Kwon <hoegeun.kwon@samsung.com>,
	Stefan Wahren <stefan.wahren@i2se.com>
Subject: [PATCH v5 14/80] drm/vc4: crtc: Assign output to channel automatically
Date: Thu,  3 Sep 2020 10:00:46 +0200	[thread overview]
Message-ID: <f9aba3814ef37156ff36f310118cdd3954dd3dc5.1599120059.git-series.maxime@cerno.tech> (raw)
In-Reply-To: <cover.dddc064d8bb83e46744336af67dcb13139e5747d.1599120059.git-series.maxime@cerno.tech>

The HVS found in the BCM2711 has 6 outputs and 3 FIFOs, with each output
being connected to a pixelvalve, and some muxing between the FIFOs and
outputs.

Any output cannot feed from any FIFO though, and they all have a bunch of
constraints.

In order to support this, let's store the possible FIFOs each output can be
assigned to in the vc4_crtc_data, and use that information at atomic_check
time to iterate over all the CRTCs enabled and assign them FIFOs.

The channel assigned is then set in the vc4_crtc_state so that the rest of
the driver can use it.

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Tested-by: Chanwoo Choi <cw00.choi@samsung.com>
Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c |  12 +-
 drivers/gpu/drm/vc4/vc4_drv.h  |   7 +-
 drivers/gpu/drm/vc4/vc4_hvs.c  |  28 ++----
 drivers/gpu/drm/vc4/vc4_kms.c  | 168 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h |  10 ++-
 drivers/gpu/drm/vc4/vc4_txp.c  |   1 +-
 6 files changed, 200 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index fe2e5675aed4..b7e47ce1476c 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -88,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
 	unsigned int cob_size;
 	u32 val;
 	int fifo_lines;
@@ -104,7 +105,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	 * Read vertical scanline which is currently composed for our
 	 * pixelvalve by the HVS, and also the scaler status.
 	 */
-	val = HVS_READ(SCALER_DISPSTATX(vc4_crtc->channel));
+	val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel));
 
 	/* Get optional system timestamp after query. */
 	if (etime)
@@ -124,7 +125,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 			*hpos += mode->crtc_htotal / 2;
 	}
 
-	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel);
+	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc_state->assigned_channel);
 	/* This is the offset we need for translating hvs -> pv scanout pos. */
 	fifo_lines = cob_size / mode->crtc_hdisplay;
 
@@ -520,7 +521,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
-	u32 chan = vc4_crtc->channel;
+	u32 chan = vc4_state->assigned_channel;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->event_lock, flags);
@@ -719,6 +720,7 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc)
 	old_vc4_state = to_vc4_crtc_state(crtc->state);
 	vc4_state->feed_txp = old_vc4_state->feed_txp;
 	vc4_state->margins = old_vc4_state->margins;
+	vc4_state->assigned_channel = old_vc4_state->assigned_channel;
 
 	__drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
 	return &vc4_state->base;
@@ -779,6 +781,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
 
 static const struct vc4_pv_data bcm2835_pv0_data = {
 	.base = {
+		.hvs_available_channels = BIT(0),
 		.hvs_output = 0,
 	},
 	.debugfs_name = "crtc0_regs",
@@ -791,6 +794,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 
 static const struct vc4_pv_data bcm2835_pv1_data = {
 	.base = {
+		.hvs_available_channels = BIT(2),
 		.hvs_output = 2,
 	},
 	.debugfs_name = "crtc1_regs",
@@ -803,6 +807,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 
 static const struct vc4_pv_data bcm2835_pv2_data = {
 	.base = {
+		.hvs_available_channels = BIT(1),
 		.hvs_output = 1,
 	},
 	.debugfs_name = "crtc2_regs",
@@ -866,7 +871,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
 				  crtc_funcs, NULL);
 	drm_crtc_helper_add(crtc, crtc_helper_funcs);
-	vc4_crtc->channel = vc4_crtc->data->hvs_output;
 	drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
 	drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
 
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index d1cf4c038180..9e81ad8331f1 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -447,6 +447,9 @@ to_vc4_encoder(struct drm_encoder *encoder)
 }
 
 struct vc4_crtc_data {
+	/* Bitmask of channels (FIFOs) of the HVS that the output can source from */
+	unsigned int hvs_available_channels;
+
 	/* Which output of the HVS this pixelvalve sources from. */
 	int hvs_output;
 };
@@ -471,9 +474,6 @@ struct vc4_crtc {
 	/* Timestamp at start of vblank irq - unaffected by lock delays. */
 	ktime_t t_vblank;
 
-	/* Which HVS channel we're using for our CRTC. */
-	int channel;
-
 	u8 lut_r[256];
 	u8 lut_g[256];
 	u8 lut_b[256];
@@ -509,6 +509,7 @@ struct vc4_crtc_state {
 	struct drm_mm_node mm;
 	bool feed_txp;
 	bool txp_armed;
+	unsigned int assigned_channel;
 
 	struct {
 		unsigned int left;
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 365425d67f3f..31a9bc5ef84e 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -161,6 +161,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	u32 i;
 
 	/* The LUT memory is laid out with each HVS channel in order,
@@ -169,7 +170,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
 	 */
 	HVS_WRITE(SCALER_GAMADDR,
 		  SCALER_GAMADDR_AUTOINC |
-		  (vc4_crtc->channel * 3 * crtc->gamma_size));
+		  (vc4_state->assigned_channel * 3 * crtc->gamma_size));
 
 	for (i = 0; i < crtc->gamma_size; i++)
 		HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
@@ -249,12 +250,12 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
 			crtc->state->event = NULL;
 		}
 
-		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+		HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 			  vc4_state->mm.start);
 
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	} else {
-		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+		HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 			  vc4_state->mm.start);
 	}
 }
@@ -264,7 +265,6 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool oneshot = vc4_state->feed_txp;
@@ -292,7 +292,7 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 					  SCALER5_DISPCTRLX_HEIGHT) |
 			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
 
-	HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);
+	HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
 }
 
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
@@ -300,8 +300,8 @@ void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-	u32 chan = vc4_crtc->channel;
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
+	unsigned int chan = vc4_state->assigned_channel;
 
 	if (HVS_READ(SCALER_DISPCTRLX(chan)) &
 	    SCALER_DISPCTRLX_ENABLE) {
@@ -332,7 +332,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_plane *plane;
 	struct vc4_plane_state *vc4_plane_state;
@@ -374,8 +373,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 		/* This sets a black background color fill, as is the case
 		 * with other DRM drivers.
 		 */
-		HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
-			  HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel)) |
+		HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
+			  HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)) |
 			  SCALER_DISPBKGND_FILL);
 
 	/* Only update DISPLIST if the CRTC was already running and is not
@@ -389,7 +388,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 		vc4_hvs_update_dlist(crtc);
 
 	if (crtc->state->color_mgmt_changed) {
-		u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel));
+		u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel));
 
 		if (crtc->state->gamma_lut) {
 			vc4_hvs_update_gamma_lut(crtc);
@@ -401,7 +400,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 			 */
 			dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
 		}
-		HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), dispbkgndx);
+		HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx);
 	}
 
 	if (debug_dump_regs) {
@@ -414,12 +413,11 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
 
-	if (vc4_crtc->data->hvs_output == 2) {
+	if (vc4_state->assigned_channel == 2) {
 		u32 dispctrl;
 		u32 dsp3_mux;
 
@@ -443,7 +441,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
 	}
 
-	HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
+	HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
 		  SCALER_DISPBKGND_AUTOHS |
 		  SCALER_DISPBKGND_GAMMA |
 		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index a41d105d4e3c..bfc7ddd49ac5 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -146,6 +146,107 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state)
 		  VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO));
 }
 
+static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4,
+				     struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned int i;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
+		u32 dispctrl;
+		u32 dsp3_mux;
+
+		if (!crtc_state->active)
+			continue;
+
+		if (vc4_state->assigned_channel != 2)
+			continue;
+
+		/*
+		 * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
+		 * FIFO X'.
+		 * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
+		 *
+		 * DSP3 is connected to FIFO2 unless the transposer is
+		 * enabled. In this case, FIFO 2 is directly accessed by the
+		 * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
+		 * route.
+		 */
+		if (vc4_state->feed_txp)
+			dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
+		else
+			dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
+
+		dispctrl = HVS_READ(SCALER_DISPCTRL) &
+			   ~SCALER_DISPCTRL_DSP3_MUX_MASK;
+		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
+	}
+}
+
+static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4,
+				     struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned char dsp2_mux = 0;
+	unsigned char dsp3_mux = 3;
+	unsigned char dsp4_mux = 3;
+	unsigned char dsp5_mux = 3;
+	unsigned int i;
+	u32 reg;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+		if (!crtc_state->active)
+			continue;
+
+		switch (vc4_crtc->data->hvs_output) {
+		case 2:
+			dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1;
+			break;
+
+		case 3:
+			dsp3_mux = vc4_state->assigned_channel;
+			break;
+
+		case 4:
+			dsp4_mux = vc4_state->assigned_channel;
+			break;
+
+		case 5:
+			dsp5_mux = vc4_state->assigned_channel;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	reg = HVS_READ(SCALER_DISPECTRL);
+	HVS_WRITE(SCALER_DISPECTRL,
+		  (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
+		  VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX));
+
+	reg = HVS_READ(SCALER_DISPCTRL);
+	HVS_WRITE(SCALER_DISPCTRL,
+		  (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
+		  VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX));
+
+	reg = HVS_READ(SCALER_DISPEOLN);
+	HVS_WRITE(SCALER_DISPEOLN,
+		  (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
+		  VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX));
+
+	reg = HVS_READ(SCALER_DISPDITHER);
+	HVS_WRITE(SCALER_DISPDITHER,
+		  (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
+		  VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX));
+}
+
 static void
 vc4_atomic_complete_commit(struct drm_atomic_state *state)
 {
@@ -157,12 +258,13 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 	int i;
 
 	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
-		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+		struct vc4_crtc_state *vc4_crtc_state;
 
 		if (!new_crtc_state->commit)
 			continue;
 
-		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
+		vc4_crtc_state = to_vc4_crtc_state(new_crtc_state);
+		vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel);
 	}
 
 	if (vc4->hvs->hvs5)
@@ -176,6 +278,11 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 
 	vc4_ctm_commit(vc4, state);
 
+	if (vc4->hvs->hvs5)
+		vc5_hvs_pv_muxing_commit(vc4, state);
+	else
+		vc4_hvs_pv_muxing_commit(vc4, state);
+
 	drm_atomic_helper_commit_planes(dev, state, 0);
 
 	drm_atomic_helper_commit_modeset_enables(dev, state);
@@ -385,8 +492,11 @@ vc4_ctm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 
 		/* CTM is being enabled or the matrix changed. */
 		if (new_crtc_state->ctm) {
+			struct vc4_crtc_state *vc4_crtc_state =
+				to_vc4_crtc_state(new_crtc_state);
+
 			/* fifo is 1-based since 0 disables CTM. */
-			int fifo = to_vc4_crtc(crtc)->channel + 1;
+			int fifo = vc4_crtc_state->assigned_channel + 1;
 
 			/* Check userland isn't trying to turn on CTM for more
 			 * than one CRTC at a time.
@@ -496,10 +606,60 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = {
 	.atomic_destroy_state = vc4_load_tracker_destroy_state,
 };
 
+#define NUM_OUTPUTS  6
+#define NUM_CHANNELS 3
+
 static int
 vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 {
-	int ret;
+	unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	int i, ret;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_crtc_state =
+			to_vc4_crtc_state(crtc_state);
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+		unsigned int matching_channels;
+
+		if (!crtc_state->active)
+			continue;
+
+		/*
+		 * The problem we have to solve here is that we have
+		 * up to 7 encoders, connected to up to 6 CRTCs.
+		 *
+		 * Those CRTCs, depending on the instance, can be
+		 * routed to 1, 2 or 3 HVS FIFOs, and we need to set
+		 * the change the muxing between FIFOs and outputs in
+		 * the HVS accordingly.
+		 *
+		 * It would be pretty hard to come up with an
+		 * algorithm that would generically solve
+		 * this. However, the current routing trees we support
+		 * allow us to simplify a bit the problem.
+		 *
+		 * Indeed, with the current supported layouts, if we
+		 * try to assign in the ascending crtc index order the
+		 * FIFOs, we can't fall into the situation where an
+		 * earlier CRTC that had multiple routes is assigned
+		 * one that was the only option for a later CRTC.
+		 *
+		 * If the layout changes and doesn't give us that in
+		 * the future, we will need to have something smarter,
+		 * but it works so far.
+		 */
+		matching_channels = unassigned_channels & vc4_crtc->data->hvs_available_channels;
+		if (matching_channels) {
+			unsigned int channel = ffs(matching_channels) - 1;
+
+			vc4_crtc_state->assigned_channel = channel;
+			unassigned_channels &= ~BIT(channel);
+		} else {
+			return -EINVAL;
+		}
+	}
 
 	ret = vc4_ctm_atomic_check(dev, state);
 	if (ret < 0)
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 91b785725555..7fbac68b6fe1 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -286,9 +286,19 @@
 
 #define SCALER_DISPID                           0x00000008
 #define SCALER_DISPECTRL                        0x0000000c
+# define SCALER_DISPECTRL_DSP2_MUX_SHIFT	31
+# define SCALER_DISPECTRL_DSP2_MUX_MASK		VC4_MASK(31, 31)
+
 #define SCALER_DISPPROF                         0x00000010
+
 #define SCALER_DISPDITHER                       0x00000014
+# define SCALER_DISPDITHER_DSP5_MUX_SHIFT	30
+# define SCALER_DISPDITHER_DSP5_MUX_MASK	VC4_MASK(31, 30)
+
 #define SCALER_DISPEOLN                         0x00000018
+# define SCALER_DISPEOLN_DSP4_MUX_SHIFT		30
+# define SCALER_DISPEOLN_DSP4_MUX_MASK		VC4_MASK(31, 30)
+
 #define SCALER_DISPLIST0                        0x00000020
 #define SCALER_DISPLIST1                        0x00000024
 #define SCALER_DISPLIST2                        0x00000028
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index f39d9900d027..a2380d856000 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -452,6 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
 }
 
 static const struct vc4_crtc_data vc4_txp_crtc_data = {
+	.hvs_available_channels = BIT(2),
 	.hvs_output = 2,
 };
 
-- 
git-series 0.9.1

WARNING: multiple messages have this Message-ID (diff)
From: Maxime Ripard <maxime@cerno.tech>
To: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>,
	Eric Anholt <eric@anholt.net>
Cc: Stefan Wahren <stefan.wahren@i2se.com>,
	Tim Gover <tim.gover@raspberrypi.com>,
	Dave Stevenson <dave.stevenson@raspberrypi.com>,
	linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	Hoegeun Kwon <hoegeun.kwon@samsung.com>,
	Chanwoo Choi <cw00.choi@samsung.com>,
	bcm-kernel-feedback-list@broadcom.com,
	linux-rpi-kernel@lists.infradead.org,
	Phil Elwell <phil@raspberrypi.com>,
	linux-arm-kernel@lists.infradead.org,
	Maxime Ripard <maxime@cerno.tech>
Subject: [PATCH v5 14/80] drm/vc4: crtc: Assign output to channel automatically
Date: Thu,  3 Sep 2020 10:00:46 +0200	[thread overview]
Message-ID: <f9aba3814ef37156ff36f310118cdd3954dd3dc5.1599120059.git-series.maxime@cerno.tech> (raw)
In-Reply-To: <cover.dddc064d8bb83e46744336af67dcb13139e5747d.1599120059.git-series.maxime@cerno.tech>

The HVS found in the BCM2711 has 6 outputs and 3 FIFOs, with each output
being connected to a pixelvalve, and some muxing between the FIFOs and
outputs.

Any output cannot feed from any FIFO though, and they all have a bunch of
constraints.

In order to support this, let's store the possible FIFOs each output can be
assigned to in the vc4_crtc_data, and use that information at atomic_check
time to iterate over all the CRTCs enabled and assign them FIFOs.

The channel assigned is then set in the vc4_crtc_state so that the rest of
the driver can use it.

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Tested-by: Chanwoo Choi <cw00.choi@samsung.com>
Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c |  12 +-
 drivers/gpu/drm/vc4/vc4_drv.h  |   7 +-
 drivers/gpu/drm/vc4/vc4_hvs.c  |  28 ++----
 drivers/gpu/drm/vc4/vc4_kms.c  | 168 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h |  10 ++-
 drivers/gpu/drm/vc4/vc4_txp.c  |   1 +-
 6 files changed, 200 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index fe2e5675aed4..b7e47ce1476c 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -88,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
 	unsigned int cob_size;
 	u32 val;
 	int fifo_lines;
@@ -104,7 +105,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	 * Read vertical scanline which is currently composed for our
 	 * pixelvalve by the HVS, and also the scaler status.
 	 */
-	val = HVS_READ(SCALER_DISPSTATX(vc4_crtc->channel));
+	val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel));
 
 	/* Get optional system timestamp after query. */
 	if (etime)
@@ -124,7 +125,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 			*hpos += mode->crtc_htotal / 2;
 	}
 
-	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel);
+	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc_state->assigned_channel);
 	/* This is the offset we need for translating hvs -> pv scanout pos. */
 	fifo_lines = cob_size / mode->crtc_hdisplay;
 
@@ -520,7 +521,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
-	u32 chan = vc4_crtc->channel;
+	u32 chan = vc4_state->assigned_channel;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->event_lock, flags);
@@ -719,6 +720,7 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc)
 	old_vc4_state = to_vc4_crtc_state(crtc->state);
 	vc4_state->feed_txp = old_vc4_state->feed_txp;
 	vc4_state->margins = old_vc4_state->margins;
+	vc4_state->assigned_channel = old_vc4_state->assigned_channel;
 
 	__drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
 	return &vc4_state->base;
@@ -779,6 +781,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
 
 static const struct vc4_pv_data bcm2835_pv0_data = {
 	.base = {
+		.hvs_available_channels = BIT(0),
 		.hvs_output = 0,
 	},
 	.debugfs_name = "crtc0_regs",
@@ -791,6 +794,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 
 static const struct vc4_pv_data bcm2835_pv1_data = {
 	.base = {
+		.hvs_available_channels = BIT(2),
 		.hvs_output = 2,
 	},
 	.debugfs_name = "crtc1_regs",
@@ -803,6 +807,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 
 static const struct vc4_pv_data bcm2835_pv2_data = {
 	.base = {
+		.hvs_available_channels = BIT(1),
 		.hvs_output = 1,
 	},
 	.debugfs_name = "crtc2_regs",
@@ -866,7 +871,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
 				  crtc_funcs, NULL);
 	drm_crtc_helper_add(crtc, crtc_helper_funcs);
-	vc4_crtc->channel = vc4_crtc->data->hvs_output;
 	drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
 	drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
 
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index d1cf4c038180..9e81ad8331f1 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -447,6 +447,9 @@ to_vc4_encoder(struct drm_encoder *encoder)
 }
 
 struct vc4_crtc_data {
+	/* Bitmask of channels (FIFOs) of the HVS that the output can source from */
+	unsigned int hvs_available_channels;
+
 	/* Which output of the HVS this pixelvalve sources from. */
 	int hvs_output;
 };
@@ -471,9 +474,6 @@ struct vc4_crtc {
 	/* Timestamp at start of vblank irq - unaffected by lock delays. */
 	ktime_t t_vblank;
 
-	/* Which HVS channel we're using for our CRTC. */
-	int channel;
-
 	u8 lut_r[256];
 	u8 lut_g[256];
 	u8 lut_b[256];
@@ -509,6 +509,7 @@ struct vc4_crtc_state {
 	struct drm_mm_node mm;
 	bool feed_txp;
 	bool txp_armed;
+	unsigned int assigned_channel;
 
 	struct {
 		unsigned int left;
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 365425d67f3f..31a9bc5ef84e 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -161,6 +161,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	u32 i;
 
 	/* The LUT memory is laid out with each HVS channel in order,
@@ -169,7 +170,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
 	 */
 	HVS_WRITE(SCALER_GAMADDR,
 		  SCALER_GAMADDR_AUTOINC |
-		  (vc4_crtc->channel * 3 * crtc->gamma_size));
+		  (vc4_state->assigned_channel * 3 * crtc->gamma_size));
 
 	for (i = 0; i < crtc->gamma_size; i++)
 		HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
@@ -249,12 +250,12 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
 			crtc->state->event = NULL;
 		}
 
-		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+		HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 			  vc4_state->mm.start);
 
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	} else {
-		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+		HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 			  vc4_state->mm.start);
 	}
 }
@@ -264,7 +265,6 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool oneshot = vc4_state->feed_txp;
@@ -292,7 +292,7 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 					  SCALER5_DISPCTRLX_HEIGHT) |
 			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
 
-	HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);
+	HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
 }
 
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
@@ -300,8 +300,8 @@ void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-	u32 chan = vc4_crtc->channel;
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
+	unsigned int chan = vc4_state->assigned_channel;
 
 	if (HVS_READ(SCALER_DISPCTRLX(chan)) &
 	    SCALER_DISPCTRLX_ENABLE) {
@@ -332,7 +332,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_plane *plane;
 	struct vc4_plane_state *vc4_plane_state;
@@ -374,8 +373,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 		/* This sets a black background color fill, as is the case
 		 * with other DRM drivers.
 		 */
-		HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
-			  HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel)) |
+		HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
+			  HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)) |
 			  SCALER_DISPBKGND_FILL);
 
 	/* Only update DISPLIST if the CRTC was already running and is not
@@ -389,7 +388,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 		vc4_hvs_update_dlist(crtc);
 
 	if (crtc->state->color_mgmt_changed) {
-		u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel));
+		u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel));
 
 		if (crtc->state->gamma_lut) {
 			vc4_hvs_update_gamma_lut(crtc);
@@ -401,7 +400,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 			 */
 			dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
 		}
-		HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), dispbkgndx);
+		HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx);
 	}
 
 	if (debug_dump_regs) {
@@ -414,12 +413,11 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
 
-	if (vc4_crtc->data->hvs_output == 2) {
+	if (vc4_state->assigned_channel == 2) {
 		u32 dispctrl;
 		u32 dsp3_mux;
 
@@ -443,7 +441,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
 	}
 
-	HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
+	HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
 		  SCALER_DISPBKGND_AUTOHS |
 		  SCALER_DISPBKGND_GAMMA |
 		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index a41d105d4e3c..bfc7ddd49ac5 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -146,6 +146,107 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state)
 		  VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO));
 }
 
+static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4,
+				     struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned int i;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
+		u32 dispctrl;
+		u32 dsp3_mux;
+
+		if (!crtc_state->active)
+			continue;
+
+		if (vc4_state->assigned_channel != 2)
+			continue;
+
+		/*
+		 * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
+		 * FIFO X'.
+		 * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
+		 *
+		 * DSP3 is connected to FIFO2 unless the transposer is
+		 * enabled. In this case, FIFO 2 is directly accessed by the
+		 * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
+		 * route.
+		 */
+		if (vc4_state->feed_txp)
+			dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
+		else
+			dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
+
+		dispctrl = HVS_READ(SCALER_DISPCTRL) &
+			   ~SCALER_DISPCTRL_DSP3_MUX_MASK;
+		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
+	}
+}
+
+static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4,
+				     struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned char dsp2_mux = 0;
+	unsigned char dsp3_mux = 3;
+	unsigned char dsp4_mux = 3;
+	unsigned char dsp5_mux = 3;
+	unsigned int i;
+	u32 reg;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+		if (!crtc_state->active)
+			continue;
+
+		switch (vc4_crtc->data->hvs_output) {
+		case 2:
+			dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1;
+			break;
+
+		case 3:
+			dsp3_mux = vc4_state->assigned_channel;
+			break;
+
+		case 4:
+			dsp4_mux = vc4_state->assigned_channel;
+			break;
+
+		case 5:
+			dsp5_mux = vc4_state->assigned_channel;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	reg = HVS_READ(SCALER_DISPECTRL);
+	HVS_WRITE(SCALER_DISPECTRL,
+		  (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
+		  VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX));
+
+	reg = HVS_READ(SCALER_DISPCTRL);
+	HVS_WRITE(SCALER_DISPCTRL,
+		  (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
+		  VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX));
+
+	reg = HVS_READ(SCALER_DISPEOLN);
+	HVS_WRITE(SCALER_DISPEOLN,
+		  (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
+		  VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX));
+
+	reg = HVS_READ(SCALER_DISPDITHER);
+	HVS_WRITE(SCALER_DISPDITHER,
+		  (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
+		  VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX));
+}
+
 static void
 vc4_atomic_complete_commit(struct drm_atomic_state *state)
 {
@@ -157,12 +258,13 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 	int i;
 
 	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
-		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+		struct vc4_crtc_state *vc4_crtc_state;
 
 		if (!new_crtc_state->commit)
 			continue;
 
-		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
+		vc4_crtc_state = to_vc4_crtc_state(new_crtc_state);
+		vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel);
 	}
 
 	if (vc4->hvs->hvs5)
@@ -176,6 +278,11 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 
 	vc4_ctm_commit(vc4, state);
 
+	if (vc4->hvs->hvs5)
+		vc5_hvs_pv_muxing_commit(vc4, state);
+	else
+		vc4_hvs_pv_muxing_commit(vc4, state);
+
 	drm_atomic_helper_commit_planes(dev, state, 0);
 
 	drm_atomic_helper_commit_modeset_enables(dev, state);
@@ -385,8 +492,11 @@ vc4_ctm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 
 		/* CTM is being enabled or the matrix changed. */
 		if (new_crtc_state->ctm) {
+			struct vc4_crtc_state *vc4_crtc_state =
+				to_vc4_crtc_state(new_crtc_state);
+
 			/* fifo is 1-based since 0 disables CTM. */
-			int fifo = to_vc4_crtc(crtc)->channel + 1;
+			int fifo = vc4_crtc_state->assigned_channel + 1;
 
 			/* Check userland isn't trying to turn on CTM for more
 			 * than one CRTC at a time.
@@ -496,10 +606,60 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = {
 	.atomic_destroy_state = vc4_load_tracker_destroy_state,
 };
 
+#define NUM_OUTPUTS  6
+#define NUM_CHANNELS 3
+
 static int
 vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 {
-	int ret;
+	unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	int i, ret;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_crtc_state =
+			to_vc4_crtc_state(crtc_state);
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+		unsigned int matching_channels;
+
+		if (!crtc_state->active)
+			continue;
+
+		/*
+		 * The problem we have to solve here is that we have
+		 * up to 7 encoders, connected to up to 6 CRTCs.
+		 *
+		 * Those CRTCs, depending on the instance, can be
+		 * routed to 1, 2 or 3 HVS FIFOs, and we need to set
+		 * the change the muxing between FIFOs and outputs in
+		 * the HVS accordingly.
+		 *
+		 * It would be pretty hard to come up with an
+		 * algorithm that would generically solve
+		 * this. However, the current routing trees we support
+		 * allow us to simplify a bit the problem.
+		 *
+		 * Indeed, with the current supported layouts, if we
+		 * try to assign in the ascending crtc index order the
+		 * FIFOs, we can't fall into the situation where an
+		 * earlier CRTC that had multiple routes is assigned
+		 * one that was the only option for a later CRTC.
+		 *
+		 * If the layout changes and doesn't give us that in
+		 * the future, we will need to have something smarter,
+		 * but it works so far.
+		 */
+		matching_channels = unassigned_channels & vc4_crtc->data->hvs_available_channels;
+		if (matching_channels) {
+			unsigned int channel = ffs(matching_channels) - 1;
+
+			vc4_crtc_state->assigned_channel = channel;
+			unassigned_channels &= ~BIT(channel);
+		} else {
+			return -EINVAL;
+		}
+	}
 
 	ret = vc4_ctm_atomic_check(dev, state);
 	if (ret < 0)
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 91b785725555..7fbac68b6fe1 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -286,9 +286,19 @@
 
 #define SCALER_DISPID                           0x00000008
 #define SCALER_DISPECTRL                        0x0000000c
+# define SCALER_DISPECTRL_DSP2_MUX_SHIFT	31
+# define SCALER_DISPECTRL_DSP2_MUX_MASK		VC4_MASK(31, 31)
+
 #define SCALER_DISPPROF                         0x00000010
+
 #define SCALER_DISPDITHER                       0x00000014
+# define SCALER_DISPDITHER_DSP5_MUX_SHIFT	30
+# define SCALER_DISPDITHER_DSP5_MUX_MASK	VC4_MASK(31, 30)
+
 #define SCALER_DISPEOLN                         0x00000018
+# define SCALER_DISPEOLN_DSP4_MUX_SHIFT		30
+# define SCALER_DISPEOLN_DSP4_MUX_MASK		VC4_MASK(31, 30)
+
 #define SCALER_DISPLIST0                        0x00000020
 #define SCALER_DISPLIST1                        0x00000024
 #define SCALER_DISPLIST2                        0x00000028
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index f39d9900d027..a2380d856000 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -452,6 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
 }
 
 static const struct vc4_crtc_data vc4_txp_crtc_data = {
+	.hvs_available_channels = BIT(2),
 	.hvs_output = 2,
 };
 
-- 
git-series 0.9.1

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

WARNING: multiple messages have this Message-ID (diff)
From: Maxime Ripard <maxime@cerno.tech>
To: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>,
	Eric Anholt <eric@anholt.net>
Cc: Stefan Wahren <stefan.wahren@i2se.com>,
	Tim Gover <tim.gover@raspberrypi.com>,
	Dave Stevenson <dave.stevenson@raspberrypi.com>,
	linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	Hoegeun Kwon <hoegeun.kwon@samsung.com>,
	Chanwoo Choi <cw00.choi@samsung.com>,
	bcm-kernel-feedback-list@broadcom.com,
	linux-rpi-kernel@lists.infradead.org,
	Phil Elwell <phil@raspberrypi.com>,
	linux-arm-kernel@lists.infradead.org,
	Maxime Ripard <maxime@cerno.tech>
Subject: [PATCH v5 14/80] drm/vc4: crtc: Assign output to channel automatically
Date: Thu,  3 Sep 2020 10:00:46 +0200	[thread overview]
Message-ID: <f9aba3814ef37156ff36f310118cdd3954dd3dc5.1599120059.git-series.maxime@cerno.tech> (raw)
In-Reply-To: <cover.dddc064d8bb83e46744336af67dcb13139e5747d.1599120059.git-series.maxime@cerno.tech>

The HVS found in the BCM2711 has 6 outputs and 3 FIFOs, with each output
being connected to a pixelvalve, and some muxing between the FIFOs and
outputs.

Any output cannot feed from any FIFO though, and they all have a bunch of
constraints.

In order to support this, let's store the possible FIFOs each output can be
assigned to in the vc4_crtc_data, and use that information at atomic_check
time to iterate over all the CRTCs enabled and assign them FIFOs.

The channel assigned is then set in the vc4_crtc_state so that the rest of
the driver can use it.

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Tested-by: Chanwoo Choi <cw00.choi@samsung.com>
Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c |  12 +-
 drivers/gpu/drm/vc4/vc4_drv.h  |   7 +-
 drivers/gpu/drm/vc4/vc4_hvs.c  |  28 ++----
 drivers/gpu/drm/vc4/vc4_kms.c  | 168 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h |  10 ++-
 drivers/gpu/drm/vc4/vc4_txp.c  |   1 +-
 6 files changed, 200 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index fe2e5675aed4..b7e47ce1476c 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -88,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
 	unsigned int cob_size;
 	u32 val;
 	int fifo_lines;
@@ -104,7 +105,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	 * Read vertical scanline which is currently composed for our
 	 * pixelvalve by the HVS, and also the scaler status.
 	 */
-	val = HVS_READ(SCALER_DISPSTATX(vc4_crtc->channel));
+	val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel));
 
 	/* Get optional system timestamp after query. */
 	if (etime)
@@ -124,7 +125,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 			*hpos += mode->crtc_htotal / 2;
 	}
 
-	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel);
+	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc_state->assigned_channel);
 	/* This is the offset we need for translating hvs -> pv scanout pos. */
 	fifo_lines = cob_size / mode->crtc_hdisplay;
 
@@ -520,7 +521,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
-	u32 chan = vc4_crtc->channel;
+	u32 chan = vc4_state->assigned_channel;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->event_lock, flags);
@@ -719,6 +720,7 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc)
 	old_vc4_state = to_vc4_crtc_state(crtc->state);
 	vc4_state->feed_txp = old_vc4_state->feed_txp;
 	vc4_state->margins = old_vc4_state->margins;
+	vc4_state->assigned_channel = old_vc4_state->assigned_channel;
 
 	__drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
 	return &vc4_state->base;
@@ -779,6 +781,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
 
 static const struct vc4_pv_data bcm2835_pv0_data = {
 	.base = {
+		.hvs_available_channels = BIT(0),
 		.hvs_output = 0,
 	},
 	.debugfs_name = "crtc0_regs",
@@ -791,6 +794,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 
 static const struct vc4_pv_data bcm2835_pv1_data = {
 	.base = {
+		.hvs_available_channels = BIT(2),
 		.hvs_output = 2,
 	},
 	.debugfs_name = "crtc1_regs",
@@ -803,6 +807,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 
 static const struct vc4_pv_data bcm2835_pv2_data = {
 	.base = {
+		.hvs_available_channels = BIT(1),
 		.hvs_output = 1,
 	},
 	.debugfs_name = "crtc2_regs",
@@ -866,7 +871,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
 				  crtc_funcs, NULL);
 	drm_crtc_helper_add(crtc, crtc_helper_funcs);
-	vc4_crtc->channel = vc4_crtc->data->hvs_output;
 	drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
 	drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
 
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index d1cf4c038180..9e81ad8331f1 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -447,6 +447,9 @@ to_vc4_encoder(struct drm_encoder *encoder)
 }
 
 struct vc4_crtc_data {
+	/* Bitmask of channels (FIFOs) of the HVS that the output can source from */
+	unsigned int hvs_available_channels;
+
 	/* Which output of the HVS this pixelvalve sources from. */
 	int hvs_output;
 };
@@ -471,9 +474,6 @@ struct vc4_crtc {
 	/* Timestamp at start of vblank irq - unaffected by lock delays. */
 	ktime_t t_vblank;
 
-	/* Which HVS channel we're using for our CRTC. */
-	int channel;
-
 	u8 lut_r[256];
 	u8 lut_g[256];
 	u8 lut_b[256];
@@ -509,6 +509,7 @@ struct vc4_crtc_state {
 	struct drm_mm_node mm;
 	bool feed_txp;
 	bool txp_armed;
+	unsigned int assigned_channel;
 
 	struct {
 		unsigned int left;
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 365425d67f3f..31a9bc5ef84e 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -161,6 +161,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	u32 i;
 
 	/* The LUT memory is laid out with each HVS channel in order,
@@ -169,7 +170,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
 	 */
 	HVS_WRITE(SCALER_GAMADDR,
 		  SCALER_GAMADDR_AUTOINC |
-		  (vc4_crtc->channel * 3 * crtc->gamma_size));
+		  (vc4_state->assigned_channel * 3 * crtc->gamma_size));
 
 	for (i = 0; i < crtc->gamma_size; i++)
 		HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
@@ -249,12 +250,12 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
 			crtc->state->event = NULL;
 		}
 
-		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+		HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 			  vc4_state->mm.start);
 
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	} else {
-		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+		HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 			  vc4_state->mm.start);
 	}
 }
@@ -264,7 +265,6 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool oneshot = vc4_state->feed_txp;
@@ -292,7 +292,7 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 					  SCALER5_DISPCTRLX_HEIGHT) |
 			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
 
-	HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);
+	HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
 }
 
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
@@ -300,8 +300,8 @@ void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-	u32 chan = vc4_crtc->channel;
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
+	unsigned int chan = vc4_state->assigned_channel;
 
 	if (HVS_READ(SCALER_DISPCTRLX(chan)) &
 	    SCALER_DISPCTRLX_ENABLE) {
@@ -332,7 +332,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_plane *plane;
 	struct vc4_plane_state *vc4_plane_state;
@@ -374,8 +373,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 		/* This sets a black background color fill, as is the case
 		 * with other DRM drivers.
 		 */
-		HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
-			  HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel)) |
+		HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
+			  HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)) |
 			  SCALER_DISPBKGND_FILL);
 
 	/* Only update DISPLIST if the CRTC was already running and is not
@@ -389,7 +388,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 		vc4_hvs_update_dlist(crtc);
 
 	if (crtc->state->color_mgmt_changed) {
-		u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel));
+		u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel));
 
 		if (crtc->state->gamma_lut) {
 			vc4_hvs_update_gamma_lut(crtc);
@@ -401,7 +400,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 			 */
 			dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
 		}
-		HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), dispbkgndx);
+		HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx);
 	}
 
 	if (debug_dump_regs) {
@@ -414,12 +413,11 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
 
-	if (vc4_crtc->data->hvs_output == 2) {
+	if (vc4_state->assigned_channel == 2) {
 		u32 dispctrl;
 		u32 dsp3_mux;
 
@@ -443,7 +441,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
 	}
 
-	HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
+	HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
 		  SCALER_DISPBKGND_AUTOHS |
 		  SCALER_DISPBKGND_GAMMA |
 		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index a41d105d4e3c..bfc7ddd49ac5 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -146,6 +146,107 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state)
 		  VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO));
 }
 
+static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4,
+				     struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned int i;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
+		u32 dispctrl;
+		u32 dsp3_mux;
+
+		if (!crtc_state->active)
+			continue;
+
+		if (vc4_state->assigned_channel != 2)
+			continue;
+
+		/*
+		 * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
+		 * FIFO X'.
+		 * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
+		 *
+		 * DSP3 is connected to FIFO2 unless the transposer is
+		 * enabled. In this case, FIFO 2 is directly accessed by the
+		 * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
+		 * route.
+		 */
+		if (vc4_state->feed_txp)
+			dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
+		else
+			dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
+
+		dispctrl = HVS_READ(SCALER_DISPCTRL) &
+			   ~SCALER_DISPCTRL_DSP3_MUX_MASK;
+		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
+	}
+}
+
+static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4,
+				     struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned char dsp2_mux = 0;
+	unsigned char dsp3_mux = 3;
+	unsigned char dsp4_mux = 3;
+	unsigned char dsp5_mux = 3;
+	unsigned int i;
+	u32 reg;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+		if (!crtc_state->active)
+			continue;
+
+		switch (vc4_crtc->data->hvs_output) {
+		case 2:
+			dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1;
+			break;
+
+		case 3:
+			dsp3_mux = vc4_state->assigned_channel;
+			break;
+
+		case 4:
+			dsp4_mux = vc4_state->assigned_channel;
+			break;
+
+		case 5:
+			dsp5_mux = vc4_state->assigned_channel;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	reg = HVS_READ(SCALER_DISPECTRL);
+	HVS_WRITE(SCALER_DISPECTRL,
+		  (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
+		  VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX));
+
+	reg = HVS_READ(SCALER_DISPCTRL);
+	HVS_WRITE(SCALER_DISPCTRL,
+		  (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
+		  VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX));
+
+	reg = HVS_READ(SCALER_DISPEOLN);
+	HVS_WRITE(SCALER_DISPEOLN,
+		  (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
+		  VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX));
+
+	reg = HVS_READ(SCALER_DISPDITHER);
+	HVS_WRITE(SCALER_DISPDITHER,
+		  (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
+		  VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX));
+}
+
 static void
 vc4_atomic_complete_commit(struct drm_atomic_state *state)
 {
@@ -157,12 +258,13 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 	int i;
 
 	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
-		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+		struct vc4_crtc_state *vc4_crtc_state;
 
 		if (!new_crtc_state->commit)
 			continue;
 
-		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
+		vc4_crtc_state = to_vc4_crtc_state(new_crtc_state);
+		vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel);
 	}
 
 	if (vc4->hvs->hvs5)
@@ -176,6 +278,11 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 
 	vc4_ctm_commit(vc4, state);
 
+	if (vc4->hvs->hvs5)
+		vc5_hvs_pv_muxing_commit(vc4, state);
+	else
+		vc4_hvs_pv_muxing_commit(vc4, state);
+
 	drm_atomic_helper_commit_planes(dev, state, 0);
 
 	drm_atomic_helper_commit_modeset_enables(dev, state);
@@ -385,8 +492,11 @@ vc4_ctm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 
 		/* CTM is being enabled or the matrix changed. */
 		if (new_crtc_state->ctm) {
+			struct vc4_crtc_state *vc4_crtc_state =
+				to_vc4_crtc_state(new_crtc_state);
+
 			/* fifo is 1-based since 0 disables CTM. */
-			int fifo = to_vc4_crtc(crtc)->channel + 1;
+			int fifo = vc4_crtc_state->assigned_channel + 1;
 
 			/* Check userland isn't trying to turn on CTM for more
 			 * than one CRTC at a time.
@@ -496,10 +606,60 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = {
 	.atomic_destroy_state = vc4_load_tracker_destroy_state,
 };
 
+#define NUM_OUTPUTS  6
+#define NUM_CHANNELS 3
+
 static int
 vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 {
-	int ret;
+	unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	int i, ret;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_crtc_state =
+			to_vc4_crtc_state(crtc_state);
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+		unsigned int matching_channels;
+
+		if (!crtc_state->active)
+			continue;
+
+		/*
+		 * The problem we have to solve here is that we have
+		 * up to 7 encoders, connected to up to 6 CRTCs.
+		 *
+		 * Those CRTCs, depending on the instance, can be
+		 * routed to 1, 2 or 3 HVS FIFOs, and we need to set
+		 * the change the muxing between FIFOs and outputs in
+		 * the HVS accordingly.
+		 *
+		 * It would be pretty hard to come up with an
+		 * algorithm that would generically solve
+		 * this. However, the current routing trees we support
+		 * allow us to simplify a bit the problem.
+		 *
+		 * Indeed, with the current supported layouts, if we
+		 * try to assign in the ascending crtc index order the
+		 * FIFOs, we can't fall into the situation where an
+		 * earlier CRTC that had multiple routes is assigned
+		 * one that was the only option for a later CRTC.
+		 *
+		 * If the layout changes and doesn't give us that in
+		 * the future, we will need to have something smarter,
+		 * but it works so far.
+		 */
+		matching_channels = unassigned_channels & vc4_crtc->data->hvs_available_channels;
+		if (matching_channels) {
+			unsigned int channel = ffs(matching_channels) - 1;
+
+			vc4_crtc_state->assigned_channel = channel;
+			unassigned_channels &= ~BIT(channel);
+		} else {
+			return -EINVAL;
+		}
+	}
 
 	ret = vc4_ctm_atomic_check(dev, state);
 	if (ret < 0)
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 91b785725555..7fbac68b6fe1 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -286,9 +286,19 @@
 
 #define SCALER_DISPID                           0x00000008
 #define SCALER_DISPECTRL                        0x0000000c
+# define SCALER_DISPECTRL_DSP2_MUX_SHIFT	31
+# define SCALER_DISPECTRL_DSP2_MUX_MASK		VC4_MASK(31, 31)
+
 #define SCALER_DISPPROF                         0x00000010
+
 #define SCALER_DISPDITHER                       0x00000014
+# define SCALER_DISPDITHER_DSP5_MUX_SHIFT	30
+# define SCALER_DISPDITHER_DSP5_MUX_MASK	VC4_MASK(31, 30)
+
 #define SCALER_DISPEOLN                         0x00000018
+# define SCALER_DISPEOLN_DSP4_MUX_SHIFT		30
+# define SCALER_DISPEOLN_DSP4_MUX_MASK		VC4_MASK(31, 30)
+
 #define SCALER_DISPLIST0                        0x00000020
 #define SCALER_DISPLIST1                        0x00000024
 #define SCALER_DISPLIST2                        0x00000028
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index f39d9900d027..a2380d856000 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -452,6 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
 }
 
 static const struct vc4_crtc_data vc4_txp_crtc_data = {
+	.hvs_available_channels = BIT(2),
 	.hvs_output = 2,
 };
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  parent reply	other threads:[~2020-09-03  8:04 UTC|newest]

Thread overview: 342+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20200904071259epcas1p3de4209531c0bc5ed6ea9ef19827b6ed5@epcas1p3.samsung.com>
2020-09-03  8:00 ` [PATCH v5 00/80] drm/vc4: Support BCM2711 Display Pipeline Maxime Ripard
2020-09-03  8:00   ` Maxime Ripard
2020-09-03  8:00   ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 01/80] dt-bindings: display: Add support for the BCM2711 HVS Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 02/80] drm/vc4: Add support for the BCM2711 HVS5 Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 03/80] drm/vc4: hvs: Boost the core clock during modeset Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 04/80] drm/vc4: plane: Change LBM alignment constraint on LBM Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 05/80] drm/vc4: plane: Optimize the LBM allocation size Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 06/80] drm/vc4: plane: Create more planes Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 07/80] drm/vc4: crtc: Deal with different number of pixel per clock Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 08/80] drm/vc4: crtc: Use a shared interrupt Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 09/80] drm/vc4: crtc: Move the cob allocation outside of bind Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 10/80] drm/vc4: crtc: Rename HVS channel to output Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 11/80] drm/vc4: crtc: Use local chan variable Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 12/80] drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 13/80] drm/vc4: kms: Convert to for_each_new_crtc_state Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-04 15:42     ` Dave Stevenson
2020-09-04 15:42       ` Dave Stevenson
2020-09-04 15:42       ` Dave Stevenson
2020-09-03  8:00   ` Maxime Ripard [this message]
2020-09-03  8:00     ` [PATCH v5 14/80] drm/vc4: crtc: Assign output to channel automatically Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 15/80] drm/vc4: crtc: Add FIFO depth to vc4_crtc_data Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 16/80] drm/vc4: crtc: Add function to compute FIFO level bits Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 17/80] drm/vc4: crtc: Rename HDMI encoder type to HDMI0 Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 18/80] drm/vc4: crtc: Add HDMI1 encoder type Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 19/80] drm/vc4: crtc: Disable color management for HVS5 Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 20/80] drm/vc4: crtc: Turn pixelvalve reset into a function Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 21/80] drm/vc4: crtc: Move PV dump to config_pv Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 22/80] drm/vc4: crtc: Move HVS init and close to a function Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 23/80] drm/vc4: crtc: Move the HVS gamma LUT setup to our init function Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 24/80] drm/vc4: hvs: Make sure our channel is reset Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 25/80] drm/vc4: crtc: Remove mode_set_nofb Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 26/80] drm/vc4: crtc: Remove redundant pixelvalve reset Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00   ` [PATCH v5 27/80] drm/vc4: crtc: Move HVS channel init before the PV initialisation Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:00     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 28/80] drm/vc4: encoder: Add finer-grained encoder callbacks Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 29/80] drm/vc4: crtc: Add a delay after disabling the PixelValve output Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 30/80] drm/vc4: crtc: Clear the PixelValve FIFO on disable Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 31/80] drm/vc4: crtc: Clear the PixelValve FIFO during configuration Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 32/80] drm/vc4: hvs: Make the stop_channel function public Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 33/80] drm/vc4: hvs: Introduce a function to get the assigned FIFO Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 34/80] drm/vc4: crtc: Move the CRTC disable out Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 35/80] drm/vc4: drv: Disable the CRTC at boot time Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 36/80] dt-bindings: display: vc4: pv: Add BCM2711 pixel valves Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 37/80] drm/vc4: crtc: Add BCM2711 pixelvalves Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 38/80] drm/vc4: hdmi: Use debugfs private field Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 39/80] drm/vc4: hdmi: Move structure to header Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 40/80] drm/vc4: hdmi: rework connectors and encoders Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 41/80] drm/vc4: hdmi: Remove DDC argument to connector_init Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 42/80] drm/vc4: hdmi: Rename hdmi to vc4_hdmi Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 43/80] drm/vc4: hdmi: Move accessors " Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 44/80] drm/vc4: hdmi: Use local vc4_hdmi directly Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 45/80] drm/vc4: hdmi: Add container_of macros for encoders and connectors Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 46/80] drm/vc4: hdmi: Pass vc4_hdmi to CEC code Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 47/80] drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 48/80] drm/vc4: hdmi: Remove vc4_dev hdmi pointer Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 49/80] drm/vc4: hdmi: Remove vc4_hdmi_connector Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 50/80] drm/vc4: hdmi: Introduce resource init and variant Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 51/80] drm/vc4: hdmi: Implement a register layout abstraction Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 52/80] drm/vc4: hdmi: Add reset callback Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 53/80] drm/vc4: hdmi: Add PHY init and disable function Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 54/80] drm/vc4: hdmi: Add PHY RNG enable / " Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 55/80] drm/vc4: hdmi: Add a CSC setup callback Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-04 15:45     ` Dave Stevenson
2020-09-04 15:45       ` Dave Stevenson
2020-09-04 15:45       ` Dave Stevenson
2020-09-03  8:01   ` [PATCH v5 56/80] drm/vc4: hdmi: Add a set_timings callback Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-04 15:46     ` Dave Stevenson
2020-09-04 15:46       ` Dave Stevenson
2020-09-04 15:46       ` Dave Stevenson
2020-09-03  8:01   ` [PATCH v5 57/80] drm/vc4: hdmi: Store the encoder type in the variant structure Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 58/80] drm/vc4: hdmi: Deal with multiple debugfs files Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 59/80] drm/vc4: hdmi: Move CEC init to its own function Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 60/80] drm/vc4: hdmi: Add CEC support flag Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 61/80] drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 62/80] drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 63/80] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 64/80] drm/vc4: hdmi: Use clk_set_min_rate instead Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 65/80] drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 66/80] drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 67/80] drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 68/80] drm/vc4: hdmi: Add audio-related callbacks Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 69/80] drm/vc4: hdmi: Deal with multiple ALSA cards Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 70/80] drm/vc4: hdmi: Remove register dumps in enable Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 71/80] drm/vc4: hdmi: Always recenter the HDMI FIFO Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 72/80] drm/vc4: hdmi: Implement finer-grained hooks Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 73/80] drm/vc4: hdmi: Do the VID_CTL configuration at once Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 74/80] drm/vc4: hdmi: Switch to blank pixels when disabled Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 75/80] drm/vc4: hdmi: Add pixel BVB clock control Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-04  9:46     ` Dave Stevenson
2020-09-04  9:46       ` Dave Stevenson
2020-09-04  9:46       ` Dave Stevenson
2020-09-07 16:21       ` Maxime Ripard
2020-09-07 16:21         ` Maxime Ripard
2020-09-07 16:21         ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 76/80] drm/vc4: hdmi: Support the BCM2711 HDMI controllers Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 77/80] dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-07 11:54     ` Hoegeun Kwon
2020-09-07 11:54       ` Hoegeun Kwon
2020-09-07 11:54       ` Hoegeun Kwon
2020-09-03  8:01   ` [PATCH v5 78/80] dt-bindings: display: vc4: Document BCM2711 VC5 Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01   ` [PATCH v5 79/80] drm/vc4: drv: Support BCM2711 Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-04 15:51     ` Dave Stevenson
2020-09-04 15:51       ` Dave Stevenson
2020-09-04 15:51       ` Dave Stevenson
2020-09-03  8:01   ` [PATCH v5 80/80] ARM: dts: bcm2711: Enable the display pipeline Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-03  8:01     ` Maxime Ripard
2020-09-07 12:03     ` Hoegeun Kwon
2020-09-07 12:03       ` Hoegeun Kwon
2020-09-07 12:03       ` Hoegeun Kwon
2020-09-08 16:31     ` Nicolas Saenz Julienne
2020-09-08 16:31       ` Nicolas Saenz Julienne
2020-09-08 16:31       ` Nicolas Saenz Julienne
2020-09-29 22:15     ` Nathan Chancellor
2020-09-29 22:15       ` Nathan Chancellor
2020-09-29 22:15       ` Nathan Chancellor
2020-09-30 14:07       ` Maxime Ripard
2020-09-30 14:07         ` Maxime Ripard
2020-09-30 14:07         ` Maxime Ripard
2020-09-30 16:38         ` Nathan Chancellor
2020-09-30 16:38           ` Nathan Chancellor
2020-09-30 16:38           ` Nathan Chancellor
2020-09-30 16:52           ` Stefan Wahren
2020-09-30 16:52             ` Stefan Wahren
2020-09-30 16:52             ` Stefan Wahren
2020-10-01  6:48             ` Maxime Ripard
2020-10-01  6:48               ` Maxime Ripard
2020-10-01  6:48               ` Maxime Ripard
2020-10-01  8:54               ` Maxime Ripard
2020-10-01  8:54                 ` Maxime Ripard
2020-10-01  8:54                 ` Maxime Ripard
2020-10-01 10:15                 ` Tim Gover
2020-10-01 10:15                   ` Tim Gover
2020-10-01 10:15                   ` Tim Gover
2020-10-01 16:47                   ` Nicolas Saenz Julienne
2020-10-01 16:47                     ` Nicolas Saenz Julienne
2020-10-01 16:47                     ` Nicolas Saenz Julienne
2020-10-01 19:45                     ` Tim Gover
2020-10-01 19:45                       ` Tim Gover
2020-10-01 19:45                       ` Tim Gover
2020-10-02 15:19                   ` Maxime Ripard
2020-10-02 15:19                     ` Maxime Ripard
2020-10-02 15:19                     ` Maxime Ripard
2020-10-02 15:57                     ` Dave Stevenson
2020-10-02 15:57                       ` Dave Stevenson
2020-10-02 15:57                       ` Dave Stevenson
2020-10-06 15:26                       ` Maxime Ripard
2020-10-06 15:26                         ` Maxime Ripard
2020-10-06 15:26                         ` Maxime Ripard
2020-10-06 17:14                         ` Dave Stevenson
2020-10-06 17:14                           ` Dave Stevenson
2020-10-06 17:14                           ` Dave Stevenson
2020-10-08  9:35                           ` Nicolas Saenz Julienne
2020-10-08  9:35                             ` Nicolas Saenz Julienne
2020-10-08  9:35                             ` Nicolas Saenz Julienne
2020-10-01  9:22           ` Nicolas Saenz Julienne
2020-10-01  9:22             ` Nicolas Saenz Julienne
2020-10-01  9:22             ` Nicolas Saenz Julienne
2020-10-01  9:33             ` Maxime Ripard
2020-10-01  9:33               ` Maxime Ripard
2020-10-01  9:33               ` Maxime Ripard
2020-10-01 18:09             ` Nathan Chancellor
2020-10-01 18:09               ` Nathan Chancellor
2020-10-01 18:09               ` Nathan Chancellor
2020-09-07 11:49   ` [PATCH v5 00/80] drm/vc4: Support BCM2711 Display Pipeline Hoegeun Kwon
2020-09-07 11:49     ` Hoegeun Kwon
2020-09-07 11:49     ` Hoegeun Kwon
2020-09-08 12:00     ` Maxime Ripard
2020-09-08 12:00       ` Maxime Ripard
2020-09-08 12:00       ` Maxime Ripard
2020-09-14 10:14       ` Hoegeun Kwon
2020-09-14 10:14         ` Hoegeun Kwon
2020-09-14 10:14         ` Hoegeun Kwon
2020-09-16 16:57         ` Maxime Ripard
2020-09-16 16:57           ` Maxime Ripard
2020-09-16 16:57           ` Maxime Ripard
2020-10-08 11:27           ` Maxime Ripard
2020-10-08 11:27             ` Maxime Ripard
2020-10-08 11:27             ` Maxime Ripard
2020-09-07 16:22   ` Maxime Ripard
2020-09-07 16:22     ` Maxime Ripard
2020-09-07 16:22     ` Maxime Ripard
2020-09-07 18:21     ` Nicolas Saenz Julienne
2020-09-07 18:21       ` Nicolas Saenz Julienne
2020-09-07 18:21       ` Nicolas Saenz Julienne

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f9aba3814ef37156ff36f310118cdd3954dd3dc5.1599120059.git-series.maxime@cerno.tech \
    --to=maxime@cerno.tech \
    --cc=bcm-kernel-feedback-list@broadcom.com \
    --cc=cw00.choi@samsung.com \
    --cc=dave.stevenson@raspberrypi.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=eric@anholt.net \
    --cc=hoegeun.kwon@samsung.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rpi-kernel@lists.infradead.org \
    --cc=nsaenzjulienne@suse.de \
    --cc=phil@raspberrypi.com \
    --cc=stefan.wahren@i2se.com \
    --cc=tim.gover@raspberrypi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.