diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2019-12-18 18:19:26 +0300 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2019-12-18 18:19:26 +0300 |
commit | 66af4a9ddac62a2614af5ce80169b6421b5c2d95 (patch) | |
tree | 91568f17d3d2c7d3743d23be0209f98563da0e81 /drivers/gpu/drm/rcar-du/rcar_du_crtc.c | |
parent | be452c4e8d1434a0095a9baa6523bb9772258d59 (diff) | |
parent | c267782c5f0efbd20c560101738e68bb30d4fad5 (diff) | |
download | linux-66af4a9ddac62a2614af5ce80169b6421b5c2d95.tar.xz |
Merge tag 'du-next-20191218' of git://linuxtv.org/pinchartl/media into drm-next
R-Car Display Unit changes:
- Color Management Module support
- LVDS encoder dual-link support enhancements
- R8A77980 support
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191218151710.GA13830@pendragon.ideasonboard.com
Diffstat (limited to 'drivers/gpu/drm/rcar-du/rcar_du_crtc.c')
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index f2ae4c410244..d73e88ddecd0 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -22,6 +22,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" @@ -476,6 +477,45 @@ static void rcar_du_crtc_wait_page_flip(struct rcar_du_crtc *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 */ @@ -620,6 +660,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. @@ -643,6 +686,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; @@ -668,6 +716,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); /* @@ -688,6 +738,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, @@ -743,6 +800,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); } @@ -1079,6 +1140,7 @@ static const struct drm_crtc_funcs crtc_funcs_gen3 = { .set_crc_source = rcar_du_crtc_set_crc_source, .verify_crc_source = rcar_du_crtc_verify_crc_source, .get_crc_sources = rcar_du_crtc_get_crc_sources, + .gamma_set = drm_atomic_helper_legacy_gamma_set, }; /* ----------------------------------------------------------------------------- @@ -1198,6 +1260,15 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex, if (ret < 0) return ret; + /* CMM might be disabled for this CRTC. */ + if (rcdu->cmms[swindex]) { + rcrtc->cmm = rcdu->cmms[swindex]; + rgrp->cmms_mask |= BIT(hwindex % 2); + + drm_mode_crtc_set_gamma_size(crtc, CM2_LUT_SIZE); + drm_crtc_enable_color_mgmt(crtc, 0, false, CM2_LUT_SIZE); + } + drm_crtc_helper_add(crtc, &crtc_helper_funcs); /* Start with vertical blanking interrupt reporting disabled. */ |