@@ -90,6 +90,7 @@ msm-y += \
disp/mdp_kms.o \
disp/msm_disp_snapshot.o \
disp/msm_disp_snapshot_util.o \
+ disp/msm_dsc_helper.o \
msm_atomic.o \
msm_atomic_tracepoints.o \
msm_debugfs.o \
new file mode 100644
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <drm/drm_fixed.h>
+
+#include "msm_drv.h"
+#include "msm_dsc_helper.h"
+
+static int get_comp_ratio(struct drm_dsc_config *dsc, u32 src_bpp)
+{
+ return mult_frac(100, src_bpp, DSC_BPP(*dsc));
+}
+
+static s64 get_bytes_per_soft_slice(struct drm_dsc_config *dsc, int intf_width, int comp_ratio)
+{
+ s64 comp_ratio_fp, num_bits_fp;
+ s64 numerator_fp, denominator_fp;
+
+ comp_ratio_fp = drm_fixp_from_fraction(comp_ratio, 100);
+ num_bits_fp = drm_fixp_from_fraction(8, 1);
+
+ numerator_fp = drm_fixp_from_fraction(dsc->slice_width * dsc->bits_per_component * 3, 1);
+ denominator_fp = drm_fixp_mul(comp_ratio_fp, num_bits_fp);
+
+ return drm_fixp_div(numerator_fp, denominator_fp);
+}
+
+u32 msm_dsc_get_eol_byte_num(struct drm_dsc_config *dsc, int intf_width, u32 src_bpp)
+{
+ u32 bytes_per_ss, extra_eol_bytes, bytes_per_intf;
+ s64 bytes_per_ss_fp;
+ int slice_per_intf = msm_dsc_get_slice_per_intf(dsc, intf_width);
+ int comp_ratio = get_comp_ratio(dsc, src_bpp);
+
+ bytes_per_ss_fp = get_bytes_per_soft_slice(dsc, intf_width, comp_ratio);
+ bytes_per_ss = drm_fixp2int_ceil(bytes_per_ss_fp);
+
+ bytes_per_intf = bytes_per_ss * slice_per_intf;
+ extra_eol_bytes = bytes_per_intf % 3;
+ if (extra_eol_bytes != 0)
+ extra_eol_bytes = 3 - extra_eol_bytes;
+
+ return extra_eol_bytes;
+}
+
+u32 msm_dsc_get_dce_bytes_per_line(struct drm_dsc_config *dsc, int intf_width)
+{
+ u32 bpp;
+ u32 dce_bytes_per_line;
+
+ bpp = DSC_BPP(*dsc);
+ dce_bytes_per_line = DIV_ROUND_UP(dsc->bits_per_pixel * intf_width, 8);
+
+ return dce_bytes_per_line;
+}
+
+int msm_dsc_get_pclk_per_line(struct drm_dsc_config *dsc, int intf_width, u32 src_bpp)
+{
+ s64 data_width;
+ int comp_ratio = get_comp_ratio(dsc, src_bpp);
+
+ if (!dsc->slice_width || (intf_width < dsc->slice_width))
+ return -EINVAL;
+
+ data_width = get_bytes_per_soft_slice(dsc, intf_width, comp_ratio);
+ data_width = drm_fixp_mul(dsc->slice_count, data_width);
+ data_width = drm_fixp_from_fraction(data_width, 3);
+
+ return drm_fixp2int_ceil(data_width);
+}
new file mode 100644
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved
+ */
+
+#ifndef MSM_DSC_HELPER_H_
+#define MSM_DSC_HELPER_H_
+
+#include <drm/display/drm_dsc_helper.h>
+#include <drm/drm_modes.h>
+
+/*
+ * Helper methods for MSM specific DSC calculations that are common between timing engine,
+ * DSI, and DP.
+ */
+
+#define MSM_DSC_SLICE_PER_PKT 1
+#define DSC_BPP(config) ((config).bits_per_pixel >> 4)
+
+static inline int msm_dsc_get_slice_per_intf(struct drm_dsc_config *dsc, int intf_width)
+{
+ return DIV_ROUND_UP(intf_width, dsc->slice_width);
+}
+
+u32 msm_dsc_get_eol_byte_num(struct drm_dsc_config *dsc, int intf_width, u32 src_bpp);
+u32 msm_dsc_get_dce_bytes_per_line(struct drm_dsc_config *dsc, int intf_width);
+int msm_dsc_get_pclk_per_line(struct drm_dsc_config *dsc, int intf_width, u32 src_bpp);
+#endif /* MSM_DSC_HELPER_H_ */
Introduce MSM-specific DSC helper methods, as some calculations are common between DP and DSC. Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com> --- drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/disp/msm_dsc_helper.c | 74 +++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/disp/msm_dsc_helper.h | 28 ++++++++++++ 3 files changed, 103 insertions(+)