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

Commit a5f0ef59 authored by Laurent Pinchart's avatar Laurent Pinchart
Browse files

drm/rcar-du: Add support for multiple groups



The R8A7790 DU has 3 CRTCs, split in two groups. Support them.

Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
parent 9e2d2de9
Loading
Loading
Loading
Loading
+14 −11
Original line number Diff line number Diff line
@@ -91,7 +91,6 @@ static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
{
	const struct drm_display_mode *mode = &rcrtc->crtc.mode;
	struct rcar_du_device *rcdu = rcrtc->group->dev;
	unsigned long clk;
	u32 value;
	u32 div;
@@ -101,9 +100,9 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
	div = DIV_ROUND_CLOSEST(clk, mode->clock * 1000);
	div = clamp(div, 1U, 64U) - 1;

	rcar_du_write(rcdu, rcrtc->index ? ESCR2 : ESCR,
	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? ESCR2 : ESCR,
			    ESCR_DCLKSEL_CLKS | div);
	rcar_du_write(rcdu, rcrtc->index ? OTAR2 : OTAR, 0);
	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0);

	/* Signal polarities */
	value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL)
@@ -143,7 +142,6 @@ void rcar_du_crtc_route_output(struct drm_crtc *crtc, unsigned int output)
void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
{
	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
	struct rcar_du_device *rcdu = rcrtc->group->dev;
	struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
	unsigned int num_planes = 0;
	unsigned int prio = 0;
@@ -189,8 +187,8 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
	/* Select display timing and dot clock generator 2 for planes associated
	 * with superposition controller 2.
	 */
	if (rcrtc->index) {
		u32 value = rcar_du_read(rcdu, DPTSR);
	if (rcrtc->index % 2) {
		u32 value = rcar_du_group_read(rcrtc->group, DPTSR);

		/* The DPTSR register is updated when the display controller is
		 * stopped. We thus need to restart the DU. Once again, sorry
@@ -200,13 +198,14 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
		 * occur only if we need to break the pre-association.
		 */
		if (value != dptsr) {
			rcar_du_write(rcdu, DPTSR, dptsr);
			rcar_du_group_write(rcrtc->group, DPTSR, dptsr);
			if (rcrtc->group->used_crtcs)
				rcar_du_group_restart(rcrtc->group);
		}
	}

	rcar_du_write(rcdu, rcrtc->index ? DS2PR : DS1PR, dspr);
	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
			    dspr);
}

static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
@@ -528,6 +527,10 @@ static const struct drm_crtc_funcs crtc_funcs = {

int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
{
	static const unsigned int mmio_offsets[] = {
		DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET
	};

	struct rcar_du_device *rcdu = rgrp->dev;
	struct platform_device *pdev = to_platform_device(rcdu->dev);
	struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index];
@@ -553,10 +556,10 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
	}

	rcrtc->group = rgrp;
	rcrtc->mmio_offset = index ? DISP2_REG_OFFSET : 0;
	rcrtc->mmio_offset = mmio_offsets[index];
	rcrtc->index = index;
	rcrtc->dpms = DRM_MODE_DPMS_OFF;
	rcrtc->plane = &rgrp->planes.planes[index];
	rcrtc->plane = &rgrp->planes.planes[index % 2];

	rcrtc->plane->crtc = crtc;

+2 −0
Original line number Diff line number Diff line
@@ -218,10 +218,12 @@ static int rcar_du_remove(struct platform_device *pdev)

static const struct rcar_du_device_info rcar_du_r8a7779_info = {
	.features = 0,
	.num_crtcs = 2,
};

static const struct rcar_du_device_info rcar_du_r8a7790_info = {
	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_ALIGN_128B,
	.num_crtcs = 3,
};

static const struct platform_device_id rcar_du_id_table[] = {
+4 −2
Original line number Diff line number Diff line
@@ -31,9 +31,11 @@ struct rcar_du_device;
/*
 * struct rcar_du_device_info - DU model-specific information
 * @features: device features (RCAR_DU_FEATURE_*)
 * @num_crtcs: total number of CRTCs
 */
struct rcar_du_device_info {
	unsigned int features;
	unsigned int num_crtcs;
};

struct rcar_du_device {
@@ -45,10 +47,10 @@ struct rcar_du_device {

	struct drm_device *ddev;

	struct rcar_du_crtc crtcs[2];
	struct rcar_du_crtc crtcs[3];
	unsigned int num_crtcs;

	struct rcar_du_group group;
	struct rcar_du_group groups[2];
};

static inline bool rcar_du_has(struct rcar_du_device *rcdu,
+2 −2
Original line number Diff line number Diff line
@@ -33,12 +33,12 @@
#include "rcar_du_group.h"
#include "rcar_du_regs.h"

static u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg)
u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg)
{
	return rcar_du_read(rgrp->dev, rgrp->mmio_offset + reg);
}

static void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data)
void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data)
{
	rcar_du_write(rgrp->dev, rgrp->mmio_offset + reg, data);
}
+3 −0
Original line number Diff line number Diff line
@@ -38,6 +38,9 @@ struct rcar_du_group {
	struct rcar_du_planes planes;
};

u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg);
void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data);

int rcar_du_group_get(struct rcar_du_group *rgrp);
void rcar_du_group_put(struct rcar_du_group *rgrp);
void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start);
Loading