@@ -866,6 +866,59 @@ static void __drm_3dlut_to_dc_3dlut(const struct drm_color_lut *lut,
866866 __to_dc_lut3d_color (& lut0 [lut_i ], lut [i ], bit_depth );
867867}
868868
869+ static void __to_dc_lut3d_32_color (struct dc_rgb * rgb ,
870+ const struct drm_color_lut32 lut ,
871+ int bit_precision )
872+ {
873+ rgb -> red = drm_color_lut32_extract (lut .red , bit_precision );
874+ rgb -> green = drm_color_lut32_extract (lut .green , bit_precision );
875+ rgb -> blue = drm_color_lut32_extract (lut .blue , bit_precision );
876+ }
877+
878+ static void __drm_3dlut32_to_dc_3dlut (const struct drm_color_lut32 * lut ,
879+ uint32_t lut3d_size ,
880+ struct tetrahedral_params * params ,
881+ bool use_tetrahedral_9 ,
882+ int bit_depth )
883+ {
884+ struct dc_rgb * lut0 ;
885+ struct dc_rgb * lut1 ;
886+ struct dc_rgb * lut2 ;
887+ struct dc_rgb * lut3 ;
888+ int lut_i , i ;
889+
890+
891+ if (use_tetrahedral_9 ) {
892+ lut0 = params -> tetrahedral_9 .lut0 ;
893+ lut1 = params -> tetrahedral_9 .lut1 ;
894+ lut2 = params -> tetrahedral_9 .lut2 ;
895+ lut3 = params -> tetrahedral_9 .lut3 ;
896+ } else {
897+ lut0 = params -> tetrahedral_17 .lut0 ;
898+ lut1 = params -> tetrahedral_17 .lut1 ;
899+ lut2 = params -> tetrahedral_17 .lut2 ;
900+ lut3 = params -> tetrahedral_17 .lut3 ;
901+ }
902+
903+ for (lut_i = 0 , i = 0 ; i < lut3d_size - 4 ; lut_i ++ , i += 4 ) {
904+ /*
905+ * We should consider the 3D LUT RGB values are distributed
906+ * along four arrays lut0-3 where the first sizes 1229 and the
907+ * other 1228. The bit depth supported for 3dlut channel is
908+ * 12-bit, but DC also supports 10-bit.
909+ *
910+ * TODO: improve color pipeline API to enable the userspace set
911+ * bit depth and 3D LUT size/stride, as specified by VA-API.
912+ */
913+ __to_dc_lut3d_32_color (& lut0 [lut_i ], lut [i ], bit_depth );
914+ __to_dc_lut3d_32_color (& lut1 [lut_i ], lut [i + 1 ], bit_depth );
915+ __to_dc_lut3d_32_color (& lut2 [lut_i ], lut [i + 2 ], bit_depth );
916+ __to_dc_lut3d_32_color (& lut3 [lut_i ], lut [i + 3 ], bit_depth );
917+ }
918+ /* lut0 has 1229 points (lut_size/4 + 1) */
919+ __to_dc_lut3d_32_color (& lut0 [lut_i ], lut [i ], bit_depth );
920+ }
921+
869922/* amdgpu_dm_atomic_lut3d - set DRM 3D LUT to DC stream
870923 * @drm_lut3d: user 3D LUT
871924 * @drm_lut3d_size: size of 3D LUT
@@ -1460,6 +1513,7 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
14601513 struct dc_transfer_func * tf = & dc_plane_state -> in_shaper_func ;
14611514 const struct drm_color_lut32 * shaper_lut ;
14621515 struct drm_device * dev = colorop -> dev ;
1516+ bool enabled = false;
14631517 u32 shaper_size ;
14641518 int i = 0 , ret = 0 ;
14651519
@@ -1481,6 +1535,7 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
14811535 ret = __set_output_tf (tf , 0 , 0 , false);
14821536 if (ret )
14831537 return ret ;
1538+ enabled = true;
14841539 }
14851540
14861541 /* 1D LUT - SHAPER LUT */
@@ -1512,12 +1567,102 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
15121567 ret = __set_output_tf_32 (tf , shaper_lut , shaper_size , false);
15131568 if (ret )
15141569 return ret ;
1570+ enabled = true;
15151571 }
15161572 }
15171573
1574+ if (!enabled )
1575+ tf -> type = TF_TYPE_BYPASS ;
1576+
1577+ return 0 ;
1578+ }
1579+
1580+ /* __set_colorop_3dlut - set DRM 3D LUT to DC stream
1581+ * @drm_lut3d: user 3D LUT
1582+ * @drm_lut3d_size: size of 3D LUT
1583+ * @lut3d: DC 3D LUT
1584+ *
1585+ * Map user 3D LUT data to DC 3D LUT and all necessary bits to program it
1586+ * on DCN accordingly.
1587+ *
1588+ * Returns:
1589+ * 0 on success. -EINVAL if drm_lut3d_size is zero.
1590+ */
1591+ static int __set_colorop_3dlut (const struct drm_color_lut32 * drm_lut3d ,
1592+ uint32_t drm_lut3d_size ,
1593+ struct dc_3dlut * lut )
1594+ {
1595+ if (!drm_lut3d_size ) {
1596+ lut -> state .bits .initialized = 0 ;
1597+ return - EINVAL ;
1598+ }
1599+
1600+ /* Only supports 17x17x17 3D LUT (12-bit) now */
1601+ lut -> lut_3d .use_12bits = true;
1602+ lut -> lut_3d .use_tetrahedral_9 = false;
1603+
1604+ lut -> state .bits .initialized = 1 ;
1605+ __drm_3dlut32_to_dc_3dlut (drm_lut3d , drm_lut3d_size , & lut -> lut_3d ,
1606+ lut -> lut_3d .use_tetrahedral_9 , 12 );
1607+
15181608 return 0 ;
15191609}
15201610
1611+ static int
1612+ __set_dm_plane_colorop_3dlut (struct drm_plane_state * plane_state ,
1613+ struct dc_plane_state * dc_plane_state ,
1614+ struct drm_colorop * colorop )
1615+ {
1616+ struct drm_colorop * old_colorop ;
1617+ struct drm_colorop_state * colorop_state = NULL , * new_colorop_state ;
1618+ struct dc_transfer_func * tf = & dc_plane_state -> in_shaper_func ;
1619+ struct drm_atomic_state * state = plane_state -> state ;
1620+ const struct amdgpu_device * adev = drm_to_adev (colorop -> dev );
1621+ const struct drm_device * dev = colorop -> dev ;
1622+ const struct drm_color_lut32 * lut3d ;
1623+ uint32_t lut3d_size ;
1624+ int i = 0 , ret = 0 ;
1625+
1626+ /* 3D LUT */
1627+ old_colorop = colorop ;
1628+ for_each_new_colorop_in_state (state , colorop , new_colorop_state , i ) {
1629+ if (new_colorop_state -> colorop == old_colorop &&
1630+ new_colorop_state -> colorop -> type == DRM_COLOROP_3D_LUT ) {
1631+ colorop_state = new_colorop_state ;
1632+ break ;
1633+ }
1634+ }
1635+
1636+ if (colorop_state && !colorop_state -> bypass && colorop -> type == DRM_COLOROP_3D_LUT ) {
1637+ if (!adev -> dm .dc -> caps .color .dpp .hw_3d_lut ) {
1638+ drm_dbg (dev , "3D LUT is not supported by hardware\n" );
1639+ return - EINVAL ;
1640+ }
1641+
1642+ drm_dbg (dev , "3D LUT colorop with ID: %d\n" , colorop -> base .id );
1643+ lut3d = __extract_blob_lut32 (colorop_state -> data , & lut3d_size );
1644+ lut3d_size = lut3d != NULL ? lut3d_size : 0 ;
1645+ ret = __set_colorop_3dlut (lut3d , lut3d_size , & dc_plane_state -> lut3d_func );
1646+ if (ret ) {
1647+ drm_dbg (dev , "3D LUT colorop with ID: %d has LUT size = %d\n" ,
1648+ colorop -> base .id , lut3d_size );
1649+ return ret ;
1650+ }
1651+
1652+ /* 3D LUT requires shaper. If shaper colorop is bypassed, enable shaper curve
1653+ * with TRANSFER_FUNCTION_LINEAR
1654+ */
1655+ if (tf -> type == TF_TYPE_BYPASS ) {
1656+ tf -> type = TF_TYPE_DISTRIBUTED_POINTS ;
1657+ tf -> tf = TRANSFER_FUNCTION_LINEAR ;
1658+ tf -> sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE ;
1659+ ret = __set_output_tf_32 (tf , NULL , 0 , false);
1660+ }
1661+ }
1662+
1663+ return ret ;
1664+ }
1665+
15211666static int
15221667__set_dm_plane_colorop_blend (struct drm_plane_state * plane_state ,
15231668 struct dc_plane_state * dc_plane_state ,
@@ -1689,6 +1834,17 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
16891834 if (!colorop )
16901835 return - EINVAL ;
16911836
1837+ /* 3D LUT */
1838+ colorop = colorop -> next ;
1839+ if (!colorop ) {
1840+ drm_dbg (dev , "no 3D LUT colorop found\n" );
1841+ return - EINVAL ;
1842+ }
1843+
1844+ ret = __set_dm_plane_colorop_3dlut (plane_state , dc_plane_state , colorop );
1845+ if (ret )
1846+ return ret ;
1847+
16921848 /* 1D Curve & LUT - BLND TF & LUT */
16931849 colorop = colorop -> next ;
16941850 if (!colorop ) {
0 commit comments