From 7707dd6022593f3edd8e182e7935870cf326f874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Oct 2023 04:08:57 +0300 Subject: drm/dp_mst: Fix fractional DSC bpp handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current code does '(bpp << 4) / 16' in the MST PBN calculation, but that is just the same as 'bpp' so the DSC codepath achieves absolutely nothing. Fix it up so that the fractional part of the bpp value is actually used instead of truncated away. 64*1006 has enough zero lsbs that we can just shift that down in the dividend and thus still manage to stick to a 32bit divisor. And while touching this, let's just make the whole thing more straightforward by making the passed in bpp value .4 binary fixed point always, instead of having to pass in different things based on whether DSC is enabled or not. v2: - Fix DSC kunit test cases. Cc: Manasi Navare Cc: Lyude Paul Cc: Harry Wentland Cc: David Francis Cc: Mikita Lipski Cc: Alex Deucher Fixes: dc48529fb14e ("drm/dp_mst: Add PBN calculation for DSC modes") Signed-off-by: Ville Syrjälä [Imre: Fix kunit test cases] Acked-by: Maxime Ripard Reviewed-by: Lyude Paul Acked-by: Harry Wentland Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20231030155843.2251023-3-imre.deak@intel.com --- include/drm/display/drm_dp_mst_helper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/drm') diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h index 4429d3b1745b..655862b3d2a4 100644 --- a/include/drm/display/drm_dp_mst_helper.h +++ b/include/drm/display/drm_dp_mst_helper.h @@ -842,7 +842,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, int drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr, int link_rate, int link_lane_count); -int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc); +int drm_dp_calc_pbn_mode(int clock, int bpp); void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_t link_encoding_cap); -- cgit v1.2.3 From 9dcf67deeab6fbc4984175278b1b2c59881dca52 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 24 Oct 2023 04:08:58 +0300 Subject: drm/dp_mst: Add helper to determine if an MST port is downstream of another port Add drm_dp_mst_port_downstream_of_parent() required by the i915 driver in a follow-up patch to resolve a BW overallocation of MST streams going through a given MST port. Cc: Lyude Paul Cc: dri-devel@lists.freedesktop.org Reviewed-by: Lyude Paul Acked-by: Maxime Ripard Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20231030155843.2251023-4-imre.deak@intel.com --- include/drm/display/drm_dp_mst_helper.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/drm') diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h index 655862b3d2a4..e44485aa74e9 100644 --- a/include/drm/display/drm_dp_mst_helper.h +++ b/include/drm/display/drm_dp_mst_helper.h @@ -892,6 +892,9 @@ drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state, struct drm_dp_mst_atomic_payload * drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state, struct drm_dp_mst_port *port); +bool drm_dp_mst_port_downstream_of_parent(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + struct drm_dp_mst_port *parent); int __must_check drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, -- cgit v1.2.3 From 1cd0a5ea427931016c3e95b20dc20f17604937cc Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 24 Oct 2023 04:08:59 +0300 Subject: drm/dp_mst: Factor out a helper to check the atomic state of a topology manager Factor out a helper to check the atomic state for one MST topology manager, returning the MST port where the BW limit check has failed. This will be used in a follow-up patch by the i915 driver to improve the BW sharing between MST streams. Cc: Lyude Paul Cc: dri-devel@lists.freedesktop.org Reviewed-by: Lyude Paul Acked-by: Maxime Ripard Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20231030155843.2251023-5-imre.deak@intel.com --- include/drm/display/drm_dp_mst_helper.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/drm') diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h index e44485aa74e9..a4aad6df71f1 100644 --- a/include/drm/display/drm_dp_mst_helper.h +++ b/include/drm/display/drm_dp_mst_helper.h @@ -916,6 +916,10 @@ int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr, int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, struct drm_dp_query_stream_enc_status_ack_reply *status); +int __must_check drm_dp_mst_atomic_check_mgr(struct drm_atomic_state *state, + struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_topology_state *mst_state, + struct drm_dp_mst_port **failing_port); int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state); int __must_check drm_dp_mst_root_conn_atomic_check(struct drm_connector_state *new_conn_state, struct drm_dp_mst_topology_mgr *mgr); -- cgit v1.2.3 From b348150406564595cf6c1be388e9797fa97c2a5d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 24 Oct 2023 04:09:02 +0300 Subject: drm/dp: Add DP_HBLANK_EXPANSION_CAPABLE and DSC_PASSTHROUGH_EN DPCD flags Add the DPCD flag to enable DSC passthrough in a last branch device, used in a follow-up i915 patch. Also add a flag to detect HBLANK expansion support in a branch device, used by a workaround in a follow-up i915 patch. Cc: Lyude Paul Cc: dri-devel@lists.freedesktop.org Reviewed-by: Stanislav Lisovskiy Acked-by: Maxime Ripard Reviewed-by: Lyude Paul Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20231030155843.2251023-8-imre.deak@intel.com --- include/drm/display/drm_dp.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/drm') diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h index e69cece404b3..763d45a612f3 100644 --- a/include/drm/display/drm_dp.h +++ b/include/drm/display/drm_dp.h @@ -148,6 +148,7 @@ #define DP_RECEIVE_PORT_0_CAP_0 0x008 # define DP_LOCAL_EDID_PRESENT (1 << 1) # define DP_ASSOCIATED_TO_PRECEDING_PORT (1 << 2) +# define DP_HBLANK_EXPANSION_CAPABLE (1 << 3) #define DP_RECEIVE_PORT_0_BUFFER_SIZE 0x009 @@ -699,6 +700,7 @@ #define DP_DSC_ENABLE 0x160 /* DP 1.4 */ # define DP_DECOMPRESSION_EN (1 << 0) +# define DP_DSC_PASSTHROUGH_EN (1 << 1) #define DP_DSC_CONFIGURATION 0x161 /* DP 2.0 */ #define DP_PSR_EN_CFG 0x170 /* XXX 1.2? */ -- cgit v1.2.3 From a6315ec25eed0e9a70cb1cfc43cf694911546a5c Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 24 Oct 2023 13:22:16 +0300 Subject: drm/dp_mst: Add HBLANK expansion quirk for Synaptics MST hubs Add a quirk for Synaptics MST hubs, which require a workaround - at leat on i915 - for some modes, on which the hub applies HBLANK expansion. These modes will only work by enabling DSC decompression for them, a follow-up patch will do this in i915. v2: - Fix the quirk name in its DocBook description. Cc: Lyude Paul Cc: dri-devel@lists.freedesktop.org Reviewed-by: Stanislav Lisovskiy Acked-by: Maxime Ripard Reviewed-by: Lyude Paul Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20231030155843.2251023-9-imre.deak@intel.com --- include/drm/display/drm_dp_helper.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/drm') diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h index 3369104e2d25..01636a679ee6 100644 --- a/include/drm/display/drm_dp_helper.h +++ b/include/drm/display/drm_dp_helper.h @@ -632,6 +632,13 @@ enum drm_dp_quirk { * the DP_MAX_LINK_RATE register reporting a lower max multiplier. */ DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS, + /** + * @DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC: + * + * The device applies HBLANK expansion for some modes, but this + * requires enabling DSC. + */ + DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC, }; /** -- cgit v1.2.3 From c1d6a22b7219bd52c66e9e038a282ba79f04be1f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 24 Oct 2023 13:22:17 +0300 Subject: drm/dp: Add helpers to calculate the link BW overhead MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add helpers drivers can use to calculate the BW allocation overhead - due to SSC, FEC, DSC and data alignment on symbol cycles - and the channel coding efficiency - due to the 8b/10b, 128b/132b encoding. On 128b/132b links the FEC overhead is part of the coding efficiency, so not accounted for in the BW allocation overhead. The drivers can use these functions to calculate a ratio, controlling the stream symbol insertion rate of the source device in each SST TU or MST MTP frame. Drivers can calculate this m/n = (pixel_data_rate * drm_dp_bw_overhead()) / (link_data_rate * drm_dp_bw_channel_coding_efficiency()) ratio for a given link and pixel stream and with that the slots_per_mtp = CEIL(64 * m / n) allocated slots per MTP for the stream in a link frame and with that the pbn = slots_per_mtp * drm_mst_get_pbn_divider() allocated PBNs for the stream on the MST link path. Take drm_dp_bw_overhead() into use in drm_dp_calc_pbn_mode(), for drivers calculating the PBN value directly. v2: - Add dockbook description to drm_dp_bw_channel_coding_efficiency(). (LKP). - Clarify the way m/n ratio is calculated in the commit log. v3: - Fix compile breakage for !CONFIG_BACKLIGHT_CLASS_DEVICE. (LKP) - Account for FEC_PM overhead (+ 0.0015625 %), add comment with the formula to calculate the total FEC overhead. (Ville) v4: - Rename DRM_DP_OVERHEAD_SSC to DRM_DP_OVERHEAD_SSC_REF_CLK. (Ville) v5: - Clarify in the commit log what MTP means. - Simplify the commit log's formula to calculate PBN. Cc: Lyude Paul Cc: Ville Syrjälä Cc: kernel test robot Cc: dri-devel@lists.freedesktop.org Reviewed-by: Stanislav Lisovskiy (v2) Acked-by: Maxime Ripard Reviewed-by: Lyude Paul Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20231107001505.3370108-1-imre.deak@intel.com --- include/drm/display/drm_dp_helper.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'include/drm') diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h index 01636a679ee6..3c59f64d4a69 100644 --- a/include/drm/display/drm_dp_helper.h +++ b/include/drm/display/drm_dp_helper.h @@ -788,4 +788,15 @@ bool drm_dp_downstream_rgb_to_ycbcr_conversion(const u8 dpcd[DP_RECEIVER_CAP_SIZ const u8 port_cap[4], u8 color_spc); int drm_dp_pcon_convert_rgb_to_ycbcr(struct drm_dp_aux *aux, u8 color_spc); +#define DRM_DP_BW_OVERHEAD_MST BIT(0) +#define DRM_DP_BW_OVERHEAD_UHBR BIT(1) +#define DRM_DP_BW_OVERHEAD_SSC_REF_CLK BIT(2) +#define DRM_DP_BW_OVERHEAD_FEC BIT(3) +#define DRM_DP_BW_OVERHEAD_DSC BIT(4) + +int drm_dp_bw_overhead(int lane_count, int hactive, + int dsc_slice_count, + int bpp_x16, unsigned long flags); +int drm_dp_bw_channel_coding_efficiency(bool is_uhbr); + #endif /* _DRM_DP_HELPER_H_ */ -- cgit v1.2.3 From 48d054c2d34cdc67acb8cc9cfac326d91f1470ed Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Wed, 8 Nov 2023 12:52:58 +0530 Subject: drm/panelreplay: dpcd register definition for panelreplay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add DPCD register definition for discovering, enabling and checking status of panel replay of the sink. Cc: Jouni Högander Cc: Arun R Murthy Cc: Jani Nikula Acked-by: Maxime Ripard Reviewed-by: Arun R Murthy Signed-off-by: Animesh Manna Link: https://patchwork.freedesktop.org/patch/msgid/20231108072303.3414118-2-animesh.manna@intel.com --- include/drm/display/drm_dp.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'include/drm') diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h index 763d45a612f3..83d2039c018b 100644 --- a/include/drm/display/drm_dp.h +++ b/include/drm/display/drm_dp.h @@ -544,6 +544,10 @@ /* DFP Capability Extension */ #define DP_DFP_CAPABILITY_EXTENSION_SUPPORT 0x0a3 /* 2.0 */ +#define DP_PANEL_REPLAY_CAP 0x0b0 /* DP 2.0 */ +# define DP_PANEL_REPLAY_SUPPORT (1 << 0) +# define DP_PANEL_REPLAY_SU_SUPPORT (1 << 1) + /* Link Configuration */ #define DP_LINK_BW_SET 0x100 # define DP_LINK_RATE_TABLE 0x00 /* eDP 1.4 */ @@ -718,6 +722,13 @@ #define DP_BRANCH_DEVICE_CTRL 0x1a1 # define DP_BRANCH_DEVICE_IRQ_HPD (1 << 0) +#define PANEL_REPLAY_CONFIG 0x1b0 /* DP 2.0 */ +# define DP_PANEL_REPLAY_ENABLE (1 << 0) +# define DP_PANEL_REPLAY_UNRECOVERABLE_ERROR_EN (1 << 3) +# define DP_PANEL_REPLAY_RFB_STORAGE_ERROR_EN (1 << 4) +# define DP_PANEL_REPLAY_ACTIVE_FRAME_CRC_ERROR_EN (1 << 5) +# define DP_PANEL_REPLAY_SU_ENABLE (1 << 6) + #define DP_PAYLOAD_ALLOCATE_SET 0x1c0 #define DP_PAYLOAD_ALLOCATE_START_TIME_SLOT 0x1c1 #define DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT 0x1c2 @@ -1107,6 +1118,18 @@ #define DP_LANE_ALIGN_STATUS_UPDATED_ESI 0x200e /* status same as 0x204 */ #define DP_SINK_STATUS_ESI 0x200f /* status same as 0x205 */ +#define DP_PANEL_REPLAY_ERROR_STATUS 0x2020 /* DP 2.1*/ +# define DP_PANEL_REPLAY_LINK_CRC_ERROR (1 << 0) +# define DP_PANEL_REPLAY_RFB_STORAGE_ERROR (1 << 1) +# define DP_PANEL_REPLAY_VSC_SDP_UNCORRECTABLE_ERROR (1 << 2) + +#define DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS 0x2022 /* DP 2.1 */ +# define DP_SINK_DEVICE_PANEL_REPLAY_STATUS_MASK (7 << 0) +# define DP_SINK_FRAME_LOCKED_SHIFT 3 +# define DP_SINK_FRAME_LOCKED_MASK (3 << 3) +# define DP_SINK_FRAME_LOCKED_STATUS_VALID_SHIFT 5 +# define DP_SINK_FRAME_LOCKED_STATUS_VALID_MASK (1 << 5) + /* Extended Receiver Capability: See DP_DPCD_REV for definitions */ #define DP_DP13_DPCD_REV 0x2200 -- cgit v1.2.3 From 0c2287c9652150cf659408b66c1789830822132f Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Fri, 10 Nov 2023 15:40:10 +0530 Subject: drm/display/dp: Add helper function to get DSC bpp precision Add helper to get the DSC bits_per_pixel precision for the DP sink. Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Reviewed-by: Sui Jingfeng Acked-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20231110101020.4067342-2-ankit.k.nautiyal@intel.com --- include/drm/display/drm_dp_helper.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/drm') diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h index 3c59f64d4a69..194715083399 100644 --- a/include/drm/display/drm_dp_helper.h +++ b/include/drm/display/drm_dp_helper.h @@ -164,6 +164,7 @@ drm_dp_is_branch(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) } /* DP/eDP DSC support */ +u8 drm_dp_dsc_sink_bpp_incr(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]); u8 drm_dp_dsc_sink_max_slice_count(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE], bool is_edp); u8 drm_dp_dsc_sink_line_buf_depth(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]); -- cgit v1.2.3 From 191dc43935d1ece82bc6c9653463b3b1cd8198fb Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 16 Nov 2023 15:18:31 +0200 Subject: drm/dp_mst: Store the MST PBN divider value in fixed point format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On UHBR links the PBN divider is a fractional number, accordingly store it in fixed point format. For now drm_dp_get_vc_payload_bw() always returns a whole number and all callers will use only the integer part of it which should preserve the current behavior. The next patch will fix drm_dp_get_vc_payload_bw() for UHBR rates returning a fractional number for those (also accounting for the channel coding efficiency correctly). Cc: Lyude Paul Cc: Harry Wentland Cc: Alex Deucher Cc: Wayne Lin Cc: amd-gfx@lists.freedesktop.org Cc: dri-devel@lists.freedesktop.org Reviewed-by: Ville Syrjälä Acked-by: Daniel Vetter Acked-by: Maarten Lankhorst [Rebased changes in dm_helpers_construct_old_payload() on drm-intel-next] Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20231116131841.1588781-2-imre.deak@intel.com --- include/drm/display/drm_dp_mst_helper.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'include/drm') diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h index a4aad6df71f1..9b19d8bd520a 100644 --- a/include/drm/display/drm_dp_mst_helper.h +++ b/include/drm/display/drm_dp_mst_helper.h @@ -25,6 +25,7 @@ #include #include #include +#include #if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) #include @@ -617,7 +618,7 @@ struct drm_dp_mst_topology_state { * @pbn_div: The current PBN divisor for this topology. The driver is expected to fill this * out itself. */ - int pbn_div; + fixed20_12 pbn_div; }; #define to_dp_mst_topology_mgr(x) container_of(x, struct drm_dp_mst_topology_mgr, base) @@ -839,8 +840,8 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); -int drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr, - int link_rate, int link_lane_count); +fixed20_12 drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr, + int link_rate, int link_lane_count); int drm_dp_calc_pbn_mode(int clock, int bpp); -- cgit v1.2.3 From d389989ed530b3d8944974b7ee866b089720bc9c Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 17 Nov 2023 17:09:27 +0200 Subject: drm/dp_mst: Fix PBN divider calculation for UHBR rates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current way of calculating the pbn_div value, the link BW per each MTP slot, worked only for DP 1.4 link rates. Fix things up for UHBR rates calculating with the correct channel coding efficiency based on the link rate. v2: - Return the fractional pbn_div value from drm_dp_get_vc_payload_bw(). v3: - Fix rounding up quotient while calculating req_slots. (Ville) Cc: Ville Syrjälä Cc: Lyude Paul Cc: dri-devel@lists.freedesktop.org Reviewed-by: Ville Syrjälä Acked-by: Daniel Vetter Acked-by: Maarten Lankhorst Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20231117150929.1767227-1-imre.deak@intel.com --- include/drm/display/drm_dp_helper.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'include/drm') diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h index 194715083399..b88cc53425e0 100644 --- a/include/drm/display/drm_dp_helper.h +++ b/include/drm/display/drm_dp_helper.h @@ -252,6 +252,19 @@ drm_edp_backlight_supported(const u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE]) return !!(edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP); } +/** + * drm_dp_is_uhbr_rate - Determine if a link rate is UHBR + * @link_rate: link rate in 10kbits/s units + * + * Determine if the provided link rate is an UHBR rate. + * + * Returns: %True if @link_rate is an UHBR rate. + */ +static inline bool drm_dp_is_uhbr_rate(int link_rate) +{ + return link_rate >= 1000000; +} + /* * DisplayPort AUX channel */ -- cgit v1.2.3 From c6fbb6bca10838485b820e8a26c23996f77ce580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 13 Oct 2023 16:13:59 +0300 Subject: drm: Fix color LUT rounding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current implementation of drm_color_lut_extract() generates weird results. Eg. if we go through all the values for 16->8bpc conversion we see the following pattern: in out (count) 0 - 7f -> 0 (128) 80 - 17f -> 1 (256) 180 - 27f -> 2 (256) 280 - 37f -> 3 (256) ... fb80 - fc7f -> fc (256) fc80 - fd7f -> fd (256) fd80 - fe7f -> fe (256) fe80 - ffff -> ff (384) So less values map to 0 and more values map 0xff, which doesn't seem particularly great. To get just the same number of input values to map to the same output values we'd just need to drop the rounding entrirely. But perhaps a better idea would be to follow the OpenGL int<->float conversion rules, in which case we get the following results: in out (count) 0 - 80 -> 0 (129) 81 - 181 -> 1 (257) 182 - 282 -> 2 (257) 283 - 383 -> 3 (257) ... fc7c - fd7c -> fc (257) fd7d - fe7d -> fd (257) fe7e - ff7e -> fe (257) ff7f - ffff -> ff (129) Note that since the divisor is constant the compiler is able to optimize away the integer division in most cases. The only exception is the _ULL() case on 32bit architectures since that gets emitted as inline asm via do_div() and thus the compiler doesn't get to optimize it. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20231013131402.24072-2-ville.syrjala@linux.intel.com Reviewed-by: Chaitanya Kumar Borah Reviewed-by: Jani Nikula Acked-by: Maxime Ripard --- include/drm/drm_color_mgmt.h | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'include/drm') diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h index 81c298488b0c..54b2b2467bfd 100644 --- a/include/drm/drm_color_mgmt.h +++ b/include/drm/drm_color_mgmt.h @@ -36,20 +36,17 @@ struct drm_plane; * * Extract a degamma/gamma LUT value provided by user (in the form of * &drm_color_lut entries) and round it to the precision supported by the - * hardware. + * hardware, following OpenGL int<->float conversion rules + * (see eg. OpenGL 4.6 specification - 2.3.5 Fixed-Point Data Conversions). */ static inline u32 drm_color_lut_extract(u32 user_input, int bit_precision) { - u32 val = user_input; - u32 max = 0xffff >> (16 - bit_precision); - - /* Round only if we're not using full precision. */ - if (bit_precision < 16) { - val += 1UL << (16 - bit_precision - 1); - val >>= 16 - bit_precision; - } - - return clamp_val(val, 0, max); + if (bit_precision > 16) + return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(user_input, (1 << bit_precision) - 1), + (1 << 16) - 1); + else + return DIV_ROUND_CLOSEST(user_input * ((1 << bit_precision) - 1), + (1 << 16) - 1); } u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n); -- cgit v1.2.3