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

Commit f025705e authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'drm/next/rcar-du' of git://linuxtv.org/pinchartl/fbdev into drm-next

rcar-du fixes
* 'drm/next/rcar-du' of git://linuxtv.org/pinchartl/fbdev:
  drm: rcar-du: Split planes pre-association 4/4 between CRTCs
  drm: rcar-du: Store the number of CRTCs per group in the group structure
  drm: rcar-du: Consider plane to CRTC associations in the plane allocator
  drm: rcar-du: Keep plane to CRTC associations when disabling a plane
  drm: rcar-du: Add plane allocation debugging
  drm: rcar-du: Rename to_rcar_du_plane_state to to_rcar_plane_state
  drm: rcar-du: Embed rcar_du_planes structure into rcar_du_group
  drm: rcar-du: Move properties from rcar_du_planes to rcar_du_device
  drm: rcar-du: Document the rcar_du_plane_state structure
  drm: rcar-du: Document the rcar_du_crtc structure
parents bdcddf95 2610abfb
Loading
Loading
Loading
Loading
+33 −28
Original line number Diff line number Diff line
@@ -195,26 +195,27 @@ void rcar_du_crtc_route_output(struct drm_crtc *crtc,

static unsigned int plane_zpos(struct rcar_du_plane *plane)
{
	return to_rcar_du_plane_state(plane->plane.state)->zpos;
	return to_rcar_plane_state(plane->plane.state)->zpos;
}

static const struct rcar_du_format_info *
plane_format(struct rcar_du_plane *plane)
{
	return to_rcar_du_plane_state(plane->plane.state)->format;
	return to_rcar_plane_state(plane->plane.state)->format;
}

static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
{
	struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
	unsigned int num_planes = 0;
	unsigned int dptsr_planes;
	unsigned int hwplanes = 0;
	unsigned int prio = 0;
	unsigned int i;
	u32 dptsr = 0;
	u32 dspr = 0;

	for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) {
		struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i];
	for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes); ++i) {
		struct rcar_du_plane *plane = &rcrtc->group->planes[i];
		unsigned int j;

		if (plane->plane.state->crtc != &rcrtc->crtc)
@@ -234,40 +235,44 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
	for (i = 0; i < num_planes; ++i) {
		struct rcar_du_plane *plane = planes[i];
		struct drm_plane_state *state = plane->plane.state;
		unsigned int index = to_rcar_du_plane_state(state)->hwindex;
		unsigned int index = to_rcar_plane_state(state)->hwindex;

		prio -= 4;
		dspr |= (index + 1) << prio;
		dptsr |= DPTSR_PnDK(index) |  DPTSR_PnTS(index);
		hwplanes |= 1 << index;

		if (plane_format(plane)->planes == 2) {
			index = (index + 1) % 8;

			prio -= 4;
			dspr |= (index + 1) << prio;
			dptsr |= DPTSR_PnDK(index) |  DPTSR_PnTS(index);
			hwplanes |= 1 << index;
		}
	}

	/* Select display timing and dot clock generator 2 for planes associated
	 * with superposition controller 2.
	 */
	if (rcrtc->index % 2) {
		/* The DPTSR register is updated when the display controller is
		 * stopped. We thus need to restart the DU. Once again, sorry
		 * for the flicker. One way to mitigate the issue would be to
		 * pre-associate planes with CRTCs (either with a fixed 4/4
		 * split, or through a module parameter). Flicker would then
		 * occur only if we need to break the pre-association.
	/* Update the planes to display timing and dot clock generator
	 * associations.
	 *
	 * Updating the DPTSR register requires restarting the CRTC group,
	 * resulting in visible flicker. To mitigate the issue only update the
	 * association if needed by enabled planes. Planes being disabled will
	 * keep their current association.
	 */
	mutex_lock(&rcrtc->group->lock);
		if (rcar_du_group_read(rcrtc->group, DPTSR) != dptsr) {
			rcar_du_group_write(rcrtc->group, DPTSR, dptsr);

	dptsr_planes = rcrtc->index % 2 ? rcrtc->group->dptsr_planes | hwplanes
		     : rcrtc->group->dptsr_planes & ~hwplanes;

	if (dptsr_planes != rcrtc->group->dptsr_planes) {
		rcar_du_group_write(rcrtc->group, DPTSR,
				    (dptsr_planes << 16) | dptsr_planes);
		rcrtc->group->dptsr_planes = dptsr_planes;

		if (rcrtc->group->used_crtcs)
			rcar_du_group_restart(rcrtc->group);
	}

	mutex_unlock(&rcrtc->group->lock);
	}

	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
			    dspr);
@@ -427,8 +432,8 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
	rcar_du_crtc_start(rcrtc);

	/* Commit the planes state. */
	for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) {
		struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i];
	for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes); ++i) {
		struct rcar_du_plane *plane = &rcrtc->group->planes[i];

		if (plane->plane.state->crtc != &rcrtc->crtc)
			continue;
@@ -592,7 +597,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
	rcrtc->enabled = false;

	ret = drm_crtc_init_with_planes(rcdu->ddev, crtc,
					&rgrp->planes.planes[index % 2].plane,
					&rgrp->planes[index % 2].plane,
					NULL, &crtc_funcs);
	if (ret < 0)
		return ret;
+14 −0
Original line number Diff line number Diff line
@@ -22,6 +22,20 @@

struct rcar_du_group;

/**
 * struct rcar_du_crtc - the CRTC, representing a DU superposition processor
 * @crtc: base DRM CRTC
 * @clock: the CRTC functional clock
 * @extclock: external pixel dot clock (optional)
 * @mmio_offset: offset of the CRTC registers in the DU MMIO block
 * @index: CRTC software and hardware index
 * @started: whether the CRTC has been started and is running
 * @event: event to post when the pending page flip completes
 * @flip_wait: wait queue used to signal page flip completion
 * @outputs: bitmask of the outputs (enum rcar_du_output) driven by this CRTC
 * @enabled: whether the CRTC is enabled, used to control system resume
 * @group: CRTC group this CRTC belongs to
 */
struct rcar_du_crtc {
	struct drm_crtc crtc;

+6 −0
Original line number Diff line number Diff line
@@ -83,6 +83,12 @@ struct rcar_du_device {

	struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];

	struct {
		struct drm_property *alpha;
		struct drm_property *colorkey;
		struct drm_property *zpos;
	} props;

	unsigned int dpad0_source;
	struct rcar_du_lvdsenc *lvds[RCAR_DU_MAX_LVDS];

+6 −0
Original line number Diff line number Diff line
@@ -85,6 +85,12 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
	 * superposition 0 to DU0 pins. DU1 pins will be configured dynamically.
	 */
	rcar_du_group_write(rgrp, DORCR, DORCR_PG1D_DS1 | DORCR_DPRS);

	/* Apply planes to CRTCs association. */
	mutex_lock(&rgrp->lock);
	rcar_du_group_write(rgrp, DPTSR, (rgrp->dptsr_planes << 16) |
			    rgrp->dptsr_planes);
	mutex_unlock(&rgrp->lock);
}

/*
+6 −2
Original line number Diff line number Diff line
@@ -25,9 +25,11 @@ struct rcar_du_device;
 * @dev: the DU device
 * @mmio_offset: registers offset in the device memory map
 * @index: group index
 * @num_crtcs: number of CRTCs in this group (1 or 2)
 * @use_count: number of users of the group (rcar_du_group_(get|put))
 * @used_crtcs: number of CRTCs currently in use
 * @lock: protects the DPTSR register
 * @lock: protects the dptsr_planes field and the DPTSR register
 * @dptsr_planes: bitmask of planes driven by dot-clock and timing generator 1
 * @planes: planes handled by the group
 */
struct rcar_du_group {
@@ -35,12 +37,14 @@ struct rcar_du_group {
	unsigned int mmio_offset;
	unsigned int index;

	unsigned int num_crtcs;
	unsigned int use_count;
	unsigned int used_crtcs;

	struct mutex lock;
	unsigned int dptsr_planes;

	struct rcar_du_planes planes;
	struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
};

u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg);
Loading