Skip to content

Commit

Permalink
drm: rcar-du: crtc: Control CMM operations
Browse files Browse the repository at this point in the history
Implement CMM handling in the crtc begin and enable atomic callbacks,
and enable CMM unit through the Display Extensional Functions
register at group setup time.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
[Fix printk format modifier for size_t variable]
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
  • Loading branch information
Jacopo Mondi authored and Laurent Pinchart committed Dec 18, 2019
1 parent 8de707a commit 78b6bb1
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 0 deletions.
61 changes: 61 additions & 0 deletions drivers/gpu/drm/rcar-du/rcar_du_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <drm/drm_plane_helper.h>
#include <drm/drm_vblank.h>

#include "rcar_cmm.h"
#include "rcar_du_crtc.h"
#include "rcar_du_drv.h"
#include "rcar_du_encoder.h"
Expand Down Expand Up @@ -474,6 +475,45 @@ static void rcar_du_crtc_wait_page_flip(struct rcar_du_crtc *rcrtc)
rcar_du_crtc_finish_page_flip(rcrtc);
}

/* -----------------------------------------------------------------------------
* Color Management Module (CMM)
*/

static int rcar_du_cmm_check(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
struct drm_property_blob *drm_lut = state->gamma_lut;
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
struct device *dev = rcrtc->dev->dev;

if (!drm_lut)
return 0;

/* We only accept fully populated LUT tables. */
if (drm_color_lut_size(drm_lut) != CM2_LUT_SIZE) {
dev_err(dev, "invalid gamma lut size: %zu bytes\n",
drm_lut->length);
return -EINVAL;
}

return 0;
}

static void rcar_du_cmm_setup(struct drm_crtc *crtc)
{
struct drm_property_blob *drm_lut = crtc->state->gamma_lut;
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
struct rcar_cmm_config cmm_config = {};

if (!rcrtc->cmm)
return;

if (drm_lut)
cmm_config.lut.table = (struct drm_color_lut *)drm_lut->data;

rcar_cmm_setup(rcrtc->cmm, &cmm_config);
}

/* -----------------------------------------------------------------------------
* Start/Stop and Suspend/Resume
*/
Expand Down Expand Up @@ -619,6 +659,9 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_disable(rcrtc);

if (rcrtc->cmm)
rcar_cmm_disable(rcrtc->cmm);

/*
* Select switch sync mode. This stops display operation and configures
* the HSYNC and VSYNC signals as inputs.
Expand All @@ -642,6 +685,11 @@ static int rcar_du_crtc_atomic_check(struct drm_crtc *crtc,
{
struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(state);
struct drm_encoder *encoder;
int ret;

ret = rcar_du_cmm_check(crtc, state);
if (ret)
return ret;

/* Store the routes from the CRTC output to the DU outputs. */
rstate->outputs = 0;
Expand All @@ -667,6 +715,8 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(crtc->state);
struct rcar_du_device *rcdu = rcrtc->dev;

if (rcrtc->cmm)
rcar_cmm_enable(rcrtc->cmm);
rcar_du_crtc_get(rcrtc);

/*
Expand All @@ -686,6 +736,13 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
}

rcar_du_crtc_start(rcrtc);

/*
* TODO: The chip manual indicates that CMM tables should be written
* after the DU channel has been activated. Investigate the impact
* of this restriction on the first displayed frame.
*/
rcar_du_cmm_setup(crtc);
}

static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
Expand Down Expand Up @@ -739,6 +796,10 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
*/
rcar_du_crtc_get(rcrtc);

/* If the active state changed, we let .atomic_enable handle CMM. */
if (crtc->state->color_mgmt_changed && !crtc->state->active_changed)
rcar_du_cmm_setup(crtc);

if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_atomic_begin(rcrtc);
}
Expand Down
10 changes: 10 additions & 0 deletions drivers/gpu/drm/rcar-du/rcar_du_group.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ static void rcar_du_group_setup_didsr(struct rcar_du_group *rgrp)
static void rcar_du_group_setup(struct rcar_du_group *rgrp)
{
struct rcar_du_device *rcdu = rgrp->dev;
u32 defr7 = DEFR7_CODE;

/* Enable extended features */
rcar_du_group_write(rgrp, DEFR, DEFR_CODE | DEFR_DEFE);
Expand All @@ -147,6 +148,15 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)

rcar_du_group_setup_pins(rgrp);

/*
* TODO: Handle routing of the DU output to CMM dynamically, as we
* should bypass CMM completely when no color management feature is
* used.
*/
defr7 |= (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0) |
(rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);
rcar_du_group_write(rgrp, DEFR7, defr7);

if (rcdu->info->gen >= 2) {
rcar_du_group_setup_defr8(rgrp);
rcar_du_group_setup_didsr(rgrp);
Expand Down
5 changes: 5 additions & 0 deletions drivers/gpu/drm/rcar-du/rcar_du_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@
#define DEFR6_MLOS1 (1 << 2)
#define DEFR6_DEFAULT (DEFR6_CODE | DEFR6_TCNE1)

#define DEFR7 0x000ec
#define DEFR7_CODE (0x7779 << 16)
#define DEFR7_CMME1 BIT(6)
#define DEFR7_CMME0 BIT(4)

/* -----------------------------------------------------------------------------
* R8A7790-only Control Registers
*/
Expand Down

0 comments on commit 78b6bb1

Please sign in to comment.