From 7cbc05cb518304b746bea00bc7c0b005217bcaf7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 17 Jun 2013 03:20:08 +0200 Subject: [PATCH] drm/rcar-du: Configure RGB output routing to DPAD0 The R8A7790 DU variant has a single RGB output called DPAD0 that can be fed with the output of DU0, DU1 or DU2. Making the routing configurable. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 5 +++ drivers/gpu/drm/rcar-du/rcar_du_drv.h | 2 ++ drivers/gpu/drm/rcar-du/rcar_du_group.c | 45 +++++++++++++++++++++++-- drivers/gpu/drm/rcar-du/rcar_du_group.h | 2 +- 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 680606ef11d8..245800ddd1a8 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -139,6 +139,11 @@ void rcar_du_crtc_route_output(struct drm_crtc *crtc, * configured when starting the CRTC. */ rcrtc->outputs |= BIT(output); + + /* Store RGB routing to DPAD0 for R8A7790. */ + if (rcar_du_has(rcdu, RCAR_DU_FEATURE_DEFR8) && + output == RCAR_DU_OUTPUT_DPAD0) + rcdu->dpad0_source = rcrtc->index; } void rcar_du_crtc_update_planes(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index d5243f493903..924f5e08f060 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h @@ -68,6 +68,8 @@ struct rcar_du_device { unsigned int num_crtcs; struct rcar_du_group groups[2]; + + unsigned int dpad0_source; }; static inline bool rcar_du_has(struct rcar_du_device *rcdu, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c index 9df6fb635c96..eb53cd97e8c6 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c @@ -27,6 +27,7 @@ * counterpart in the DU documentation, that models those semi-global resources. */ +#include #include #include "rcar_du_drv.h" @@ -43,6 +44,22 @@ void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data) rcar_du_write(rgrp->dev, rgrp->mmio_offset + reg, data); } +static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp) +{ + u32 defr8 = DEFR8_CODE | DEFR8_DEFE8; + + if (!rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_DEFR8)) + return; + + /* The DEFR8 register for the first group also controls RGB output + * routing to DPAD0 + */ + if (rgrp->index == 0) + defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source); + + rcar_du_group_write(rgrp, DEFR8, defr8); +} + static void rcar_du_group_setup(struct rcar_du_group *rgrp) { /* Enable extended features */ @@ -51,8 +68,8 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp) rcar_du_group_write(rgrp, DEFR3, DEFR3_CODE | DEFR3_DEFE3); rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE); rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5); - if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_DEFR8)) - rcar_du_group_write(rgrp, DEFR8, DEFR8_CODE | DEFR8_DEFE8); + + rcar_du_group_setup_defr8(rgrp); /* Use DS1PR and DS2PR to configure planes priorities and connects the * superposition 0 to DU0 pins. DU1 pins will be configured dynamically. @@ -128,7 +145,27 @@ void rcar_du_group_restart(struct rcar_du_group *rgrp) __rcar_du_group_start_stop(rgrp, true); } -void rcar_du_group_set_routing(struct rcar_du_group *rgrp) +static int rcar_du_set_dpad0_routing(struct rcar_du_device *rcdu) +{ + int ret; + + /* 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. + */ + ret = clk_prepare_enable(rcdu->crtcs[0].clock); + if (ret < 0) + return ret; + + rcar_du_group_setup_defr8(&rcdu->groups[0]); + + clk_disable_unprepare(rcdu->crtcs[0].clock); + + return 0; +} + +int rcar_du_group_set_routing(struct rcar_du_group *rgrp) { struct rcar_du_crtc *crtc0 = &rgrp->dev->crtcs[rgrp->index * 2]; u32 dorcr = rcar_du_group_read(rgrp, DORCR); @@ -145,4 +182,6 @@ void rcar_du_group_set_routing(struct rcar_du_group *rgrp) dorcr |= DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_DS2; rcar_du_group_write(rgrp, DORCR, dorcr); + + return rcar_du_set_dpad0_routing(rgrp->dev); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h index 4487e83fb2c1..5025930972ec 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h @@ -45,6 +45,6 @@ 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); void rcar_du_group_restart(struct rcar_du_group *rgrp); -void rcar_du_group_set_routing(struct rcar_du_group *rgrp); +int rcar_du_group_set_routing(struct rcar_du_group *rgrp); #endif /* __RCAR_DU_GROUP_H__ */ -- 2.20.1