[PATCH 2/2] drm: rcar-du: Configure pixel clock polarity

Laurent Pinchart laurent.pinchart+renesas at ideasonboard.com
Thu May 14 15:06:57 UTC 2020


The R-Car DU supports inverting the polarity of the output pixel clock.
At the moment the driver hardcodes the clock polarity to drive signals
on the rising edge of the clock. Configure it instead based on the needs
of the display pipeline.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas at ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 31 +++++++++++++++++++++++++-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h |  2 ++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index fbe927278634..e86b3192a991 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -212,6 +212,8 @@ static const struct soc_device_attribute rcar_du_r8a7795_es1[] = {
 
 static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
 {
+	const struct rcar_du_crtc_state *state =
+		to_rcar_crtc_state(rcrtc->crtc.state);
 	const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode;
 	struct rcar_du_device *rcdu = rcrtc->dev;
 	unsigned long mode_clock = mode->clock * 1000;
@@ -286,6 +288,9 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
 		escr = params.escr;
 	}
 
+	if (state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
+		escr |= ESCR_DCLKOINV;
+
 	dev_dbg(rcrtc->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr);
 
 	rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr);
@@ -684,6 +689,8 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
 static int rcar_du_crtc_atomic_check(struct drm_crtc *crtc,
 				     struct drm_crtc_state *state)
 {
+	const unsigned int bus_flags_mask = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE
+					  | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
 	struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(state);
 	struct drm_connector_state *conn_state;
 	struct drm_connector *connector;
@@ -694,11 +701,15 @@ static int rcar_du_crtc_atomic_check(struct drm_crtc *crtc,
 	if (ret)
 		return ret;
 
-	/* Store the routes from the CRTC output to the DU outputs. */
+	/*
+	 * Store the routes from the CRTC output to the DU outputs and validate
+	 * the bus flags.
+	 */
 	rstate->outputs = 0;
 
 	for_each_new_connector_in_state(state->state, connector, conn_state, i) {
 		struct drm_encoder *encoder = conn_state->best_encoder;
+		struct drm_bridge *bridge;
 
 		if (!encoder)
 			continue;
@@ -708,8 +719,22 @@ static int rcar_du_crtc_atomic_check(struct drm_crtc *crtc,
 			continue;
 
 		rstate->outputs |= BIT(to_rcar_encoder(encoder)->output);
+
+		bridge = drm_bridge_chain_get_first_bridge(encoder);
+
+		if (bridge && bridge->timings)
+			rstate->bus_flags |= bridge->timings->input_bus_flags;
+		else
+			rstate->bus_flags |= connector->display_info.bus_flags;
 	}
 
+	/*
+	 * If multiple connectors require different clock edges the
+	 * configuration is invalid.
+	 */
+	if (rstate->bus_flags == bus_flags_mask)
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -944,6 +969,8 @@ rcar_du_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
 
 	__drm_atomic_helper_crtc_duplicate_state(crtc, &copy->state);
 
+	copy->bus_flags = 0;
+
 	return &copy->state;
 }
 
@@ -979,6 +1006,8 @@ static void rcar_du_crtc_reset(struct drm_crtc *crtc)
 	state->crc.source = VSP1_DU_CRC_NONE;
 	state->crc.index = 0;
 
+	state->bus_flags = 0;
+
 	crtc->state = &state->state;
 	crtc->state->crtc = crtc;
 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index 5f2940c42225..652b798154ff 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -83,12 +83,14 @@ struct rcar_du_crtc {
  * @state: base DRM CRTC state
  * @crc: CRC computation configuration
  * @outputs: bitmask of the outputs (enum rcar_du_output) driven by this CRTC
+ * @bus_flags: signal polarities for the CRTC output bus (DRM_BUS_FLAG_*)
  */
 struct rcar_du_crtc_state {
 	struct drm_crtc_state state;
 
 	struct vsp1_du_crc_config crc;
 	unsigned int outputs;
+	unsigned int bus_flags;
 };
 
 #define to_rcar_crtc_state(s) container_of(s, struct rcar_du_crtc_state, state)
-- 
Regards,

Laurent Pinchart



More information about the dri-devel mailing list