From patchwork Fri Apr 21 09:18:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liviu Dudau X-Patchwork-Id: 97876 Delivered-To: patch@linaro.org Received: by 10.140.109.52 with SMTP id k49csp225960qgf; Fri, 21 Apr 2017 02:19:09 -0700 (PDT) X-Received: by 10.84.222.8 with SMTP id w8mr14758079pls.103.1492766349381; Fri, 21 Apr 2017 02:19:09 -0700 (PDT) Return-Path: Received: from gabe.freedesktop.org (gabe.freedesktop.org. [131.252.210.177]) by mx.google.com with ESMTPS id j5si9731865pga.203.2017.04.21.02.19.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 21 Apr 2017 02:19:09 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) client-ip=131.252.210.177; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A994A6E3F6; Fri, 21 Apr 2017 09:18:56 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from cam-smtp0.cambridge.arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by gabe.freedesktop.org (Postfix) with ESMTPS id E0FC06E3F3 for ; Fri, 21 Apr 2017 09:18:54 +0000 (UTC) Received: from e110455-lin.cambridge.arm.com (e110455-lin.cambridge.arm.com [10.2.131.9]) by cam-smtp0.cambridge.arm.com (8.13.8/8.13.8) with ESMTP id v3L9ImWX025801; Fri, 21 Apr 2017 10:18:49 +0100 From: Liviu Dudau To: Brian Starkey Subject: [PATCH 08/12] drm: mali-dp: Add CTM support Date: Fri, 21 Apr 2017 10:18:44 +0100 Message-Id: <20170421091848.4666-9-Liviu.Dudau@arm.com> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20170421091848.4666-1-Liviu.Dudau@arm.com> References: <20170421091848.4666-1-Liviu.Dudau@arm.com> Cc: Mihail Atanassov , Mali DP Maintainers , DRI devel X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Mihail Atanassov All DPs have a COLORADJ matrix which is applied prior to output gamma. Attach that to the CTM property. Also, ensure the input CTM's coefficients can fit in the DP registers' Q3.12 format. Signed-off-by: Mihail Atanassov Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_crtc.c | 64 +++++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/arm/malidp_drv.c | 35 ++++++++++++++++++++- drivers/gpu/drm/arm/malidp_drv.h | 1 + drivers/gpu/drm/arm/malidp_hw.h | 1 + drivers/gpu/drm/arm/malidp_regs.h | 1 + 5 files changed, 98 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index 27ab09459b9d..8f2e1ae51ba0 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -195,6 +195,58 @@ static int malidp_crtc_atomic_check_gamma(struct drm_crtc *crtc, return 0; } +/* + * Check if there is a new CTM and if it contains valid input. Valid here means + * that the number is inside the representable range for a Q3.12 number, + * excluding truncating the fractional part of the input data. + * + * The COLORADJ registers can be changed atomically. + */ +static int malidp_crtc_atomic_check_ctm(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct malidp_crtc_state *mc = to_malidp_crtc_state(state); + struct drm_color_ctm *ctm; + int i; + + if (!state->color_mgmt_changed) + return 0; + + if (!state->ctm) + return 0; + + if (crtc->state->ctm && (crtc->state->ctm->base.id == + state->ctm->base.id)) + return 0; + + /* + * The size of the ctm is checked in + * drm_atomic_replace_property_blob_from_id. + */ + ctm = (struct drm_color_ctm *)state->ctm->data; + for (i = 0; i < ARRAY_SIZE(ctm->matrix); ++i) { + /* Convert from S31.32 to Q3.12. */ + s64 val = ctm->matrix[i]; + u32 mag = ((((u64)val) & ~BIT_ULL(63)) >> 20) & + GENMASK_ULL(14, 0); + + /* + * Convert to 2s complement and check the destination's top bit + * for overflow. NB: Can't check before converting or it'd + * incorrectly reject the case: + * sign == 1 + * mag == 0x2000 + */ + if (val & BIT_ULL(63)) + mag = ~mag + 1; + if (!!(val & BIT_ULL(63)) != !!(mag & BIT(14))) + return -EINVAL; + mc->coloradj_coeffs[i] = mag; + } + + return 0; +} + static int malidp_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -204,6 +256,7 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc, const struct drm_plane_state *pstate; u32 rot_mem_free, rot_mem_usable; int rotated_planes = 0; + int ret; /* * check if there is enough rotation memory available for planes @@ -270,7 +323,10 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc, } } - return malidp_crtc_atomic_check_gamma(crtc, state); + ret = malidp_crtc_atomic_check_gamma(crtc, state); + ret = ret ? ret : malidp_crtc_atomic_check_ctm(crtc, state); + + return ret; } static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = { @@ -295,6 +351,8 @@ static struct drm_crtc_state *malidp_crtc_duplicate_state(struct drm_crtc *crtc) __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); memcpy(state->gamma_coeffs, old_state->gamma_coeffs, sizeof(state->gamma_coeffs)); + memcpy(state->coloradj_coeffs, old_state->coloradj_coeffs, + sizeof(state->coloradj_coeffs)); return &state->base; } @@ -392,8 +450,8 @@ int malidp_crtc_init(struct drm_device *drm) drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs); drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE); - /* No inverse-gamma and color adjustments yet. */ - drm_crtc_enable_color_mgmt(&malidp->crtc, 0, false, MALIDP_GAMMA_LUT_SIZE); + /* No inverse-gamma: it is per-plane */ + drm_crtc_enable_color_mgmt(&malidp->crtc, 0, true, MALIDP_GAMMA_LUT_SIZE); return 0; diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 1eb6bbc5118a..eae41e26b819 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -79,6 +79,37 @@ static void malidp_atomic_commit_update_gamma(struct drm_crtc *crtc, } } +static +void malidp_atomic_commit_update_coloradj(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) +{ + struct malidp_drm *malidp = crtc_to_malidp_device(crtc); + struct malidp_hw_device *hwdev = malidp->dev; + int i; + + if (!crtc->state->color_mgmt_changed) + return; + + if (!crtc->state->ctm) { + malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_CADJ, + MALIDP_DE_DISPLAY_FUNC); + } else { + struct malidp_crtc_state *mc = + to_malidp_crtc_state(crtc->state); + + if (!old_state->ctm || (crtc->state->ctm->base.id != + old_state->ctm->base.id)) + for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; ++i) + malidp_hw_write(hwdev, + mc->coloradj_coeffs[i], + hwdev->map.coeffs_base + + MALIDP_COLOR_ADJ_COEF + 4 * i); + + malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_CADJ, + MALIDP_DE_DISPLAY_FUNC); + } +} + /* * set the "config valid" bit and wait until the hardware acts on it */ @@ -145,8 +176,10 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_commit_modeset_disables(drm, state); - for_each_crtc_in_state(state, crtc, old_crtc_state, i) + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { malidp_atomic_commit_update_gamma(crtc, old_crtc_state); + malidp_atomic_commit_update_coloradj(crtc, old_crtc_state); + } drm_atomic_helper_commit_planes(drm, state, 0); diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h index f5abd8bfbd2b..e1c784dcdd92 100644 --- a/drivers/gpu/drm/arm/malidp_drv.h +++ b/drivers/gpu/drm/arm/malidp_drv.h @@ -51,6 +51,7 @@ struct malidp_plane_state { struct malidp_crtc_state { struct drm_crtc_state base; u32 gamma_coeffs[MALIDP_COEFFTAB_NUM_COEFFS]; + u32 coloradj_coeffs[MALIDP_COLORADJ_NUM_COEFFS]; }; #define to_malidp_crtc_state(x) container_of(x, struct malidp_crtc_state, base) diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h index c2df6b6e7645..470fe71724a3 100644 --- a/drivers/gpu/drm/arm/malidp_hw.h +++ b/drivers/gpu/drm/arm/malidp_hw.h @@ -259,6 +259,7 @@ static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev, #define MALIDP_BGND_COLOR_G 0x000 #define MALIDP_BGND_COLOR_B 0x000 +#define MALIDP_COLORADJ_NUM_COEFFS 12 #define MALIDP_COEFFTAB_NUM_COEFFS 64 #define MALIDP_GAMMA_LUT_SIZE 4096 diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h index 28252c5b31b5..4bf338d4172e 100644 --- a/drivers/gpu/drm/arm/malidp_regs.h +++ b/drivers/gpu/drm/arm/malidp_regs.h @@ -64,6 +64,7 @@ /* bit masks that are common between products */ #define MALIDP_CFG_VALID (1 << 0) #define MALIDP_DISP_FUNC_GAMMA (1 << 0) +#define MALIDP_DISP_FUNC_CADJ (1 << 4) #define MALIDP_DISP_FUNC_ILACED (1 << 8) /* register offsets for IRQ management */