Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34a04f2b authored by Laurent Pinchart's avatar Laurent Pinchart
Browse files

drm: rcar-du: Add VSP1 compositor support



Configure the plane source at plane setup time to source frames from
memory or from the VSP1.

Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
parent af8ad962
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -90,6 +90,8 @@ struct rcar_du_device {
	} props;

	unsigned int dpad0_source;
	unsigned int vspd1_sink;

	struct rcar_du_lvdsenc *lvds[RCAR_DU_MAX_LVDS];

	struct {
+14 −10
Original line number Diff line number Diff line
@@ -49,11 +49,15 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
	u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;

	/* The DEFR8 register for the first group also controls RGB output
	 * routing to DPAD0 for DU instances that support it.
	 * routing to DPAD0 and VSPD1 routing to DU0/1/2 for DU instances that
	 * support it.
	 */
	if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1 &&
	    rgrp->index == 0)
	if (rgrp->index == 0) {
		if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1)
			defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
		if (rgrp->dev->vspd1_sink == 2)
			defr8 |= DEFR8_VSCS;
	}

	rcar_du_group_write(rgrp, DEFR8, defr8);
}
@@ -162,17 +166,17 @@ void rcar_du_group_restart(struct rcar_du_group *rgrp)
	__rcar_du_group_start_stop(rgrp, true);
}

static int rcar_du_set_dpad0_routing(struct rcar_du_device *rcdu)
int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu)
{
	int ret;

	if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_EXT_CTRL_REGS))
		return 0;

	/* RGB output routing to DPAD0 is configured in the DEFR8 register of
	 * the first group. As this function can be called with the DU0 and DU1
	 * CRTCs disabled, we need to enable the first group clock before
	 * accessing the register.
	/* RGB output routing to DPAD0 and VSP1D routing to DU0/1/2 are
	 * configured in the DEFR8 register of the first group. As this function
	 * can be called with the DU0 and DU1 CRTCs disabled, we need to enable
	 * the first group clock before accessing the register.
	 */
	ret = clk_prepare_enable(rcdu->crtcs[0].clock);
	if (ret < 0)
@@ -203,5 +207,5 @@ int rcar_du_group_set_routing(struct rcar_du_group *rgrp)

	rcar_du_group_write(rgrp, DORCR, dorcr);

	return rcar_du_set_dpad0_routing(rgrp->dev);
	return rcar_du_set_dpad0_vsp1_routing(rgrp->dev);
}
+2 −0
Original line number Diff line number Diff line
@@ -58,4 +58,6 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start);
void rcar_du_group_restart(struct rcar_du_group *rgrp);
int rcar_du_group_set_routing(struct rcar_du_group *rgrp);

int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu);

#endif /* __RCAR_DU_GROUP_H__ */
+12 −4
Original line number Diff line number Diff line
@@ -217,17 +217,25 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
 */

static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
					struct rcar_du_plane_state *state)
					struct rcar_du_plane_state *new_state)
{
	const struct rcar_du_format_info *cur_format;
	struct rcar_du_plane_state *cur_state;

	cur_format = to_rcar_plane_state(plane->plane.state)->format;
	cur_state = to_rcar_plane_state(plane->plane.state);

	/* Lowering the number of planes doesn't strictly require reallocation
	 * as the extra hardware plane will be freed when committing, but doing
	 * so could lead to more fragmentation.
	 */
	return !cur_format || cur_format->planes != state->format->planes;
	if (!cur_state->format ||
	    cur_state->format->planes != new_state->format->planes)
		return true;

	/* Reallocate hardware planes if the source has changed. */
	if (cur_state->source != new_state->source)
		return true;

	return false;
}

static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
+51 −35
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <drm/drm_plane_helper.h>

#include "rcar_du_drv.h"
#include "rcar_du_group.h"
#include "rcar_du_kms.h"
#include "rcar_du_plane.h"
#include "rcar_du_regs.h"
@@ -35,27 +36,24 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
		      data);
}

static void rcar_du_plane_setup_scanout(struct rcar_du_plane *plane)
static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
					const struct rcar_du_plane_state *state)
{
	struct rcar_du_plane_state *state =
		to_rcar_plane_state(plane->plane.state);
	struct drm_framebuffer *fb = plane->plane.state->fb;
	struct rcar_du_group *rgrp = plane->group;
	unsigned int src_x = state->state.src_x >> 16;
	unsigned int src_y = state->state.src_y >> 16;
	unsigned int index = state->hwindex;
	struct drm_gem_cma_object *gem;
	unsigned int pitch;
	bool interlaced;
	unsigned int i;
	u32 dma[2];

	interlaced = state->state.crtc->state->adjusted_mode.flags
		   & DRM_MODE_FLAG_INTERLACE;

	/* Memory pitch (expressed in pixels). Must be doubled for interlaced
	 * operation with 32bpp formats.
	 */
	if (state->source == RCAR_DU_PLANE_MEMORY) {
		struct drm_framebuffer *fb = state->state.fb;
		struct drm_gem_cma_object *gem;
		unsigned int i;

		if (state->format->planes == 2)
			pitch = fb->pitches[0];
		else
@@ -65,7 +63,15 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_plane *plane)
			gem = drm_fb_cma_get_gem_obj(fb, i);
			dma[i] = gem->paddr + fb->offsets[i];
		}
	} else {
		pitch = state->state.src_w >> 16;
		dma[0] = 0;
		dma[1] = 0;
	}

	/* Memory pitch (expressed in pixels). Must be doubled for interlaced
	 * operation with 32bpp formats.
	 */
	rcar_du_plane_write(rgrp, index, PnMWR,
			    (interlaced && state->format->bpp == 32) ?
			    pitch * 2 : pitch);
@@ -101,12 +107,10 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_plane *plane)
	}
}

static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
				     unsigned int index)
static void rcar_du_plane_setup_mode(struct rcar_du_group *rgrp,
				     unsigned int index,
				     const struct rcar_du_plane_state *state)
{
	struct rcar_du_plane_state *state =
		to_rcar_plane_state(plane->plane.state);
	struct rcar_du_group *rgrp = plane->group;
	u32 colorkey;
	u32 pnmr;

@@ -164,12 +168,10 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
	}
}

static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
				       unsigned int index)
static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
				       unsigned int index,
				       const struct rcar_du_plane_state *state)
{
	struct rcar_du_plane_state *state =
		to_rcar_plane_state(plane->plane.state);
	struct rcar_du_group *rgrp = plane->group;
	u32 ddcr2 = PnDDCR2_CODE;
	u32 ddcr4;

@@ -179,7 +181,7 @@ static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
	 * field in DDCR4.
	 */

	rcar_du_plane_setup_mode(plane, index);
	rcar_du_plane_setup_mode(rgrp, index, state);

	if (state->format->planes == 2) {
		if (state->hwindex != index) {
@@ -199,14 +201,16 @@ static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
	rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);

	ddcr4 = state->format->edf | PnDDCR4_CODE;
	if (state->source != RCAR_DU_PLANE_MEMORY)
		ddcr4 |= PnDDCR4_VSPS;

	rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);

	/* Destination position and size */
	rcar_du_plane_write(rgrp, index, PnDSXR, plane->plane.state->crtc_w);
	rcar_du_plane_write(rgrp, index, PnDSYR, plane->plane.state->crtc_h);
	rcar_du_plane_write(rgrp, index, PnDPXR, plane->plane.state->crtc_x);
	rcar_du_plane_write(rgrp, index, PnDPYR, plane->plane.state->crtc_y);
	rcar_du_plane_write(rgrp, index, PnDSXR, state->state.crtc_w);
	rcar_du_plane_write(rgrp, index, PnDSYR, state->state.crtc_h);
	rcar_du_plane_write(rgrp, index, PnDPXR, state->state.crtc_x);
	rcar_du_plane_write(rgrp, index, PnDPYR, state->state.crtc_y);

	/* Wrap-around and blinking, disabled */
	rcar_du_plane_write(rgrp, index, PnWASPR, 0);
@@ -219,12 +223,24 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane)
{
	struct rcar_du_plane_state *state =
		to_rcar_plane_state(plane->plane.state);
	struct rcar_du_group *rgrp = plane->group;

	rcar_du_plane_setup_format(plane, state->hwindex);
	rcar_du_plane_setup_format(rgrp, state->hwindex, state);
	if (state->format->planes == 2)
		rcar_du_plane_setup_format(plane, (state->hwindex + 1) % 8);
		rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
					   state);

	rcar_du_plane_setup_scanout(plane);
	rcar_du_plane_setup_scanout(rgrp, state);

	if (state->source == RCAR_DU_PLANE_VSPD1) {
		unsigned int vspd1_sink = rgrp->index ? 2 : 0;
		struct rcar_du_device *rcdu = rgrp->dev;

		if (rcdu->vspd1_sink != vspd1_sink) {
			rcdu->vspd1_sink = vspd1_sink;
			rcar_du_set_dpad0_vsp1_routing(rcdu);
		}
	}
}

static int rcar_du_plane_atomic_check(struct drm_plane *plane,
Loading