@@ -623,6 +623,86 @@ amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf)
623623 }
624624}
625625
626+ static void __to_dc_lut3d_color (struct dc_rgb * rgb ,
627+ const struct drm_color_lut lut ,
628+ int bit_precision )
629+ {
630+ rgb -> red = drm_color_lut_extract (lut .red , bit_precision );
631+ rgb -> green = drm_color_lut_extract (lut .green , bit_precision );
632+ rgb -> blue = drm_color_lut_extract (lut .blue , bit_precision );
633+ }
634+
635+ static void __drm_3dlut_to_dc_3dlut (const struct drm_color_lut * lut ,
636+ uint32_t lut3d_size ,
637+ struct tetrahedral_params * params ,
638+ bool use_tetrahedral_9 ,
639+ int bit_depth )
640+ {
641+ struct dc_rgb * lut0 ;
642+ struct dc_rgb * lut1 ;
643+ struct dc_rgb * lut2 ;
644+ struct dc_rgb * lut3 ;
645+ int lut_i , i ;
646+
647+
648+ if (use_tetrahedral_9 ) {
649+ lut0 = params -> tetrahedral_9 .lut0 ;
650+ lut1 = params -> tetrahedral_9 .lut1 ;
651+ lut2 = params -> tetrahedral_9 .lut2 ;
652+ lut3 = params -> tetrahedral_9 .lut3 ;
653+ } else {
654+ lut0 = params -> tetrahedral_17 .lut0 ;
655+ lut1 = params -> tetrahedral_17 .lut1 ;
656+ lut2 = params -> tetrahedral_17 .lut2 ;
657+ lut3 = params -> tetrahedral_17 .lut3 ;
658+ }
659+
660+ for (lut_i = 0 , i = 0 ; i < lut3d_size - 4 ; lut_i ++ , i += 4 ) {
661+ /*
662+ * We should consider the 3D LUT RGB values are distributed
663+ * along four arrays lut0-3 where the first sizes 1229 and the
664+ * other 1228. The bit depth supported for 3dlut channel is
665+ * 12-bit, but DC also supports 10-bit.
666+ *
667+ * TODO: improve color pipeline API to enable the userspace set
668+ * bit depth and 3D LUT size/stride, as specified by VA-API.
669+ */
670+ __to_dc_lut3d_color (& lut0 [lut_i ], lut [i ], bit_depth );
671+ __to_dc_lut3d_color (& lut1 [lut_i ], lut [i + 1 ], bit_depth );
672+ __to_dc_lut3d_color (& lut2 [lut_i ], lut [i + 2 ], bit_depth );
673+ __to_dc_lut3d_color (& lut3 [lut_i ], lut [i + 3 ], bit_depth );
674+ }
675+ /* lut0 has 1229 points (lut_size/4 + 1) */
676+ __to_dc_lut3d_color (& lut0 [lut_i ], lut [i ], bit_depth );
677+ }
678+
679+ /* amdgpu_dm_atomic_lut3d - set DRM 3D LUT to DC stream
680+ * @drm_lut3d: user 3D LUT
681+ * @drm_lut3d_size: size of 3D LUT
682+ * @lut3d: DC 3D LUT
683+ *
684+ * Map user 3D LUT data to DC 3D LUT and all necessary bits to program it
685+ * on DCN accordingly.
686+ */
687+ static void amdgpu_dm_atomic_lut3d (const struct drm_color_lut * drm_lut3d ,
688+ uint32_t drm_lut3d_size ,
689+ struct dc_3dlut * lut )
690+ {
691+ if (!drm_lut3d_size ) {
692+ lut -> state .bits .initialized = 0 ;
693+ } else {
694+ /* Stride and bit depth are not programmable by API yet.
695+ * Therefore, only supports 17x17x17 3D LUT (12-bit).
696+ */
697+ lut -> lut_3d .use_tetrahedral_9 = false;
698+ lut -> lut_3d .use_12bits = true;
699+ lut -> state .bits .initialized = 1 ;
700+ __drm_3dlut_to_dc_3dlut (drm_lut3d , drm_lut3d_size , & lut -> lut_3d ,
701+ lut -> lut_3d .use_tetrahedral_9 ,
702+ MAX_COLOR_3DLUT_BITDEPTH );
703+ }
704+ }
705+
626706static int amdgpu_dm_atomic_shaper_lut (const struct drm_color_lut * shaper_lut ,
627707 bool has_rom ,
628708 enum dc_transfer_func_predefined tf ,
@@ -665,8 +745,8 @@ int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev,
665745 struct drm_plane_state * plane_state )
666746{
667747 struct dm_plane_state * dm_plane_state = to_dm_plane_state (plane_state );
668- const struct drm_color_lut * shaper = NULL ;
669- uint32_t exp_size , size ;
748+ const struct drm_color_lut * shaper = NULL , * lut3d = NULL ;
749+ uint32_t exp_size , size , dim_size = MAX_COLOR_3DLUT_SIZE ;
670750 bool has_3dlut = adev -> dm .dc -> caps .color .dpp .hw_3d_lut ;
671751
672752 /* shaper LUT is only available if 3D LUT color caps */
@@ -680,6 +760,17 @@ int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev,
680760 return - EINVAL ;
681761 }
682762
763+ /* The number of 3D LUT entries is the dimension size cubed */
764+ exp_size = has_3dlut ? dim_size * dim_size * dim_size : 0 ;
765+ lut3d = __extract_blob_lut (dm_plane_state -> lut3d , & size );
766+
767+ if (lut3d && size != exp_size ) {
768+ drm_dbg (& adev -> ddev ,
769+ "Invalid 3D LUT size. Should be %u but got %u.\n" ,
770+ exp_size , size );
771+ return - EINVAL ;
772+ }
773+
683774 return 0 ;
684775}
685776
@@ -976,16 +1067,19 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
9761067{
9771068 struct dm_plane_state * dm_plane_state = to_dm_plane_state (plane_state );
9781069 enum amdgpu_transfer_function shaper_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT ;
979- const struct drm_color_lut * shaper_lut ;
980- uint32_t shaper_size ;
1070+ const struct drm_color_lut * shaper_lut , * lut3d ;
1071+ uint32_t shaper_size , lut3d_size ;
9811072 int ret ;
9821073
9831074 dc_plane_state -> hdr_mult = dc_fixpt_from_s3132 (dm_plane_state -> hdr_mult );
9841075
9851076 shaper_lut = __extract_blob_lut (dm_plane_state -> shaper_lut , & shaper_size );
9861077 shaper_size = shaper_lut != NULL ? shaper_size : 0 ;
9871078 shaper_tf = dm_plane_state -> shaper_tf ;
1079+ lut3d = __extract_blob_lut (dm_plane_state -> lut3d , & lut3d_size );
1080+ lut3d_size = lut3d != NULL ? lut3d_size : 0 ;
9881081
1082+ amdgpu_dm_atomic_lut3d (lut3d , lut3d_size , dc_plane_state -> lut3d_func );
9891083 ret = amdgpu_dm_atomic_shaper_lut (shaper_lut , false,
9901084 amdgpu_tf_to_dc_tf (shaper_tf ),
9911085 shaper_size ,
0 commit comments