From nobody Tue Feb 10 00:02:56 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D8EFC04E69 for ; Thu, 10 Aug 2023 16:06:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236351AbjHJQGK (ORCPT ); Thu, 10 Aug 2023 12:06:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33556 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236553AbjHJQFT (ORCPT ); Thu, 10 Aug 2023 12:05:19 -0400 Received: from fanzine2.igalia.com (fanzine2.igalia.com [213.97.179.56]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CEB3A3AAF for ; Thu, 10 Aug 2023 09:04:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=9D+sOG90D4swtOov18+zIz0GOUaWYMvws/wo1WCwL5I=; b=DxdrX/dLbfzG23bLvw11clvFMg DO3hen4LLZDo8qfjYm61Wb4vBEbPqwPLNOxgMrMqw/f3K7lo7jiEl4dkoPPiL1W05s60Zk8nJiQ9/ WYAgHH+9nTKDyD62CB30jgevAPymqvJTTTPuIout/CVr9WBgkOotBE8ule0ljmGa0jKlzMOGOim3s CpiaTBmpbzuou5wKLHK3wegBFQjlzAcOJDgE70JQmT5K723f4oGCIMBngMiRFnGGIAL9uHilGSBX1 tpET4LuB4Mp+tegxHIE4sqA0OwCZXE/pfx0xIkILE8K7erIHwlIfO+cHyDI5W6YRo/HsojaR0cfO0 exXAiIxw==; Received: from [38.44.68.151] (helo=killbill.home) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1qU890-00GjYD-Cs; Thu, 10 Aug 2023 18:04:14 +0200 From: Melissa Wen To: amd-gfx@lists.freedesktop.org, Harry Wentland , Rodrigo Siqueira , sunpeng.li@amd.com, Alex Deucher , dri-devel@lists.freedesktop.org, christian.koenig@amd.com, Xinhui.Pan@amd.com, airlied@gmail.com, daniel@ffwll.ch Cc: Joshua Ashton , Sebastian Wick , Xaver Hugl , Shashank Sharma , Nicholas Kazlauskas , sungjoon.kim@amd.com, Alex Hung , Pekka Paalanen , Simon Ser , kernel-dev@igalia.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 26/34] drm/amd/display: add plane 3D LUT support Date: Thu, 10 Aug 2023 15:03:06 -0100 Message-Id: <20230810160314.48225-27-mwen@igalia.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230810160314.48225-1-mwen@igalia.com> References: <20230810160314.48225-1-mwen@igalia.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Wire up DC 3D LUT to DM plane color management (pre-blending). On AMD display HW, 3D LUT comes after a shaper curve and we always have to program a shaper curve to delinearize or normalize the color space before applying a 3D LUT (since we have a reduced number of LUT entries). In this version, the default values of 3D LUT for size and bit_depth are 17x17x17 and 12-bit, but we already provide here a more generic mechanisms to program other supported values (9x9x9 size and 10-bit). v2: - started with plane 3D LUT instead of CRTC 3D LUT support Reviewed-by: Harry Wentland (v1) Signed-off-by: Melissa Wen --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 96 ++++++++++++++++++- 2 files changed, 94 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gp= u/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 347ecff2c920..025a7eb5c8aa 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8062,6 +8062,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic= _state *state, bundle->surface_updates[planes_count].gamut_remap_matrix =3D &dc_plane-= >gamut_remap_matrix; bundle->surface_updates[planes_count].hdr_mult =3D dc_plane->hdr_mult; bundle->surface_updates[planes_count].func_shaper =3D dc_plane->in_shap= er_func; + bundle->surface_updates[planes_count].lut3d_func =3D dc_plane->lut3d_fu= nc; } =20 amdgpu_dm_plane_fill_dc_scaling_info(dm->adev, new_plane_state, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/driv= ers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c index 90ec09ca4118..58c4797f506e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c @@ -598,6 +598,85 @@ amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf) } } =20 +static void __to_dc_lut3d_color(struct dc_rgb *rgb, + const struct drm_color_lut lut, + int bit_precision) +{ + rgb->red =3D drm_color_lut_extract(lut.red, bit_precision); + rgb->green =3D drm_color_lut_extract(lut.green, bit_precision); + rgb->blue =3D drm_color_lut_extract(lut.blue, bit_precision); +} + +static void __drm_3dlut_to_dc_3dlut(const struct drm_color_lut *lut, + uint32_t lut3d_size, + struct tetrahedral_params *params, + bool use_tetrahedral_9, + int bit_depth) +{ + struct dc_rgb *lut0; + struct dc_rgb *lut1; + struct dc_rgb *lut2; + struct dc_rgb *lut3; + int lut_i, i; + + + if (use_tetrahedral_9) { + lut0 =3D params->tetrahedral_9.lut0; + lut1 =3D params->tetrahedral_9.lut1; + lut2 =3D params->tetrahedral_9.lut2; + lut3 =3D params->tetrahedral_9.lut3; + } else { + lut0 =3D params->tetrahedral_17.lut0; + lut1 =3D params->tetrahedral_17.lut1; + lut2 =3D params->tetrahedral_17.lut2; + lut3 =3D params->tetrahedral_17.lut3; + } + + for (lut_i =3D 0, i =3D 0; i < lut3d_size - 4; lut_i++, i +=3D 4) { + /* We should consider the 3dlut RGB values are distributed + * along four arrays lut0-3 where the first sizes 1229 and the + * other 1228. The bit depth supported for 3dlut channel is + * 12-bit, but DC also supports 10-bit. + * + * TODO: improve color pipeline API to enable the userspace set + * bit depth and 3D LUT size/stride, as specified by VA-API. + */ + __to_dc_lut3d_color(&lut0[lut_i], lut[i], bit_depth); + __to_dc_lut3d_color(&lut1[lut_i], lut[i + 1], bit_depth); + __to_dc_lut3d_color(&lut2[lut_i], lut[i + 2], bit_depth); + __to_dc_lut3d_color(&lut3[lut_i], lut[i + 3], bit_depth); + } + /* lut0 has 1229 points (lut_size/4 + 1) */ + __to_dc_lut3d_color(&lut0[lut_i], lut[i], bit_depth); +} + +/* amdgpu_dm_atomic_lut3d - set DRM 3D LUT to DC stream + * @drm_lut3d: DRM CRTC (user) 3D LUT + * @drm_lut3d_size: size of 3D LUT + * @lut3d: DC 3D LUT + * + * Map DRM CRTC 3D LUT to DC 3D LUT and all necessary bits to program it + * on DCN MPC accordingly. + */ +static void amdgpu_dm_atomic_lut3d(const struct drm_color_lut *drm_lut, + uint32_t drm_lut3d_size, + struct dc_3dlut *lut) +{ + if (!drm_lut3d_size) { + lut->state.bits.initialized =3D 0; + } else { + /* Stride and bit depth are not programmable by API yet. + * Therefore, only supports 17x17x17 3D LUT (12-bit). + */ + lut->lut_3d.use_tetrahedral_9 =3D false; + lut->lut_3d.use_12bits =3D true; + lut->state.bits.initialized =3D 1; + __drm_3dlut_to_dc_3dlut(drm_lut, drm_lut3d_size, &lut->lut_3d, + lut->lut_3d.use_tetrahedral_9, + MAX_COLOR_3DLUT_BITDEPTH); + } +} + static int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_= lut, bool has_rom, enum dc_transfer_func_predefined tf, @@ -652,7 +731,7 @@ int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *a= dev, struct drm_plane_state *plane_state) { struct dm_plane_state *dm_plane_state =3D to_dm_plane_state(plane_state); - const struct drm_color_lut *shaper =3D NULL; + const struct drm_color_lut *shaper =3D NULL, *lut3d =3D NULL; uint32_t exp_size, size; =20 /* shaper LUT is only available if 3D LUT color caps*/ @@ -663,6 +742,14 @@ int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *= adev, drm_dbg(&adev->ddev, "Invalid Shaper LUT size. Should be %u but got %u.\n", exp_size, size); + } + + exp_size =3D amdgpu_dm_get_lut3d_size(adev, MAX_COLOR_3DLUT_ENTRIES); + lut3d =3D __extract_blob_lut(dm_plane_state->lut3d, &size); + + if (lut3d && size !=3D exp_size) { + drm_dbg(&adev->ddev, "Invalid 3D LUT size. Should be %u but got %u.\n", + exp_size, size); return -EINVAL; } =20 @@ -962,8 +1049,8 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_= state *plane_state, { struct dm_plane_state *dm_plane_state =3D to_dm_plane_state(plane_state); enum amdgpu_transfer_function shaper_tf =3D AMDGPU_TRANSFER_FUNCTION_DEFA= ULT; - const struct drm_color_lut *shaper_lut; - uint32_t shaper_size; + const struct drm_color_lut *shaper_lut, *lut3d; + uint32_t shaper_size, lut3d_size; int ret; =20 /* We have nothing to do here, return */ @@ -975,7 +1062,10 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane= _state *plane_state, shaper_lut =3D __extract_blob_lut(dm_plane_state->shaper_lut, &shaper_siz= e); shaper_size =3D shaper_lut !=3D NULL ? shaper_size : 0; shaper_tf =3D dm_plane_state->shaper_tf; + lut3d =3D __extract_blob_lut(dm_plane_state->lut3d, &lut3d_size); + lut3d_size =3D lut3d !=3D NULL ? lut3d_size : 0; =20 + amdgpu_dm_atomic_lut3d(lut3d, lut3d_size, dc_plane_state->lut3d_func); ret =3D amdgpu_dm_atomic_shaper_lut(shaper_lut, false, amdgpu_tf_to_dc_tf(shaper_tf), shaper_size, --=20 2.40.1