From: Samson Tam <samson....@amd.com>

[Why]
Enable adaptive scaler support for DCN401

[How]
- Enable build flag for SPL
- Set prefer_easf flag to true
- Apply light linear scaling policy based on transfer function and pixel
  format.  Choose between linear or non-linear scaling
- Set matrix_mode based on pixel format
- Disable ring estimator
- Add missing EASF register defines, masks, and writes
- Disable EASF if scale ratio or number of taps is unsupported and when
  bypassing the scaler
- Add debug flags and registry keys for debugging SPL and EASF
- Add support for Visual Confirm with EASF

Reviewed-by: Rodrigo Siqueira <rodrigo.sique...@amd.com>
Signed-off-by: Samson Tam <samson....@amd.com>
---
 .../gpu/drm/amd/display/dc/core/dc_resource.c |  11 +-
 drivers/gpu/drm/amd/display/dc/dc.h           |   3 +
 .../gpu/drm/amd/display/dc/dc_spl_translate.c |  15 +-
 .../amd/display/dc/dpp/dcn401/dcn401_dpp.h    |   6 +-
 .../display/dc/dpp/dcn401/dcn401_dpp_dscl.c   | 207 +++++++++++++++++-
 .../dc/resource/dcn401/dcn401_resource.c      |   1 +
 .../dc/resource/dcn401/dcn401_resource.h      |  48 +++-
 drivers/gpu/drm/amd/display/dc/spl/dc_spl.c   |  95 ++++++--
 .../gpu/drm/amd/display/dc/spl/dc_spl_types.h |  30 ++-
 9 files changed, 382 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 70c39eef99e5..ce1991e06049 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1500,8 +1500,8 @@ bool resource_build_scaling_params(struct pipe_ctx 
*pipe_ctx)
        pipe_ctx->plane_res.scl_data.format = 
convert_pixel_format_to_dalsurface(
                        pipe_ctx->plane_state->format);
 
-       if (pipe_ctx->stream->ctx->dc->config.use_spl)  {
 #if defined(CONFIG_DRM_AMD_DC_FP)
+       if ((pipe_ctx->stream->ctx->dc->config.use_spl) && 
(!pipe_ctx->stream->ctx->dc->debug.disable_spl)) {
                struct spl_in *spl_in = &pipe_ctx->plane_res.spl_in;
                struct spl_out *spl_out = &pipe_ctx->plane_res.spl_out;
 
@@ -1516,15 +1516,18 @@ bool resource_build_scaling_params(struct pipe_ctx 
*pipe_ctx)
 
                // Convert pipe_ctx to respective input params for SPL
                translate_SPL_in_params_from_pipe_ctx(pipe_ctx, spl_in);
+               /* Pass visual confirm debug information */
+               calculate_adjust_recout_for_visual_confirm(pipe_ctx,
+                       &spl_in->debug.visual_confirm_base_offset,
+                       &spl_in->debug.visual_confirm_dpp_offset);
                // Set SPL output parameters to dscl_prog_data to be used for 
hw registers
                spl_out->dscl_prog_data = resource_get_dscl_prog_data(pipe_ctx);
                // Calculate scaler parameters from SPL
                res = spl_calculate_scaler_params(spl_in, spl_out);
                // Convert respective out params from SPL to scaler data
                translate_SPL_out_params_to_pipe_ctx(pipe_ctx, spl_out);
-#endif
        } else {
-
+#endif
        /* depends on h_active */
        calculate_recout(pipe_ctx);
        /* depends on pixel format */
@@ -1604,7 +1607,9 @@ bool resource_build_scaling_params(struct pipe_ctx 
*pipe_ctx)
                pipe_ctx->plane_res.scl_data.viewport.height = 
MIN_VIEWPORT_SIZE;
        if (pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE)
                pipe_ctx->plane_res.scl_data.viewport.width = MIN_VIEWPORT_SIZE;
+#ifdef CONFIG_DRM_AMD_DC_FP
        }
+#endif
        DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d  
Recout: height:%d width:%d x:%d y:%d  HACTIVE:%d VACTIVE:%d\n"
                        "src_rect: height:%d width:%d x:%d y:%d  dst_rect: 
height:%d width:%d x:%d y:%d  clip_rect: height:%d width:%d x:%d y:%d\n",
                        __func__,
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index fd948e4cec0d..5ae74558632b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1038,6 +1038,9 @@ struct dc_debug_options {
        union dmub_fams2_global_feature_config fams2_config;
        bool enable_legacy_clock_update;
        unsigned int force_cositing;
+       unsigned int disable_spl;
+       unsigned int force_easf;
+       unsigned int force_lls;
 };
 
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c 
b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
index daf97688e901..6e37b166802b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
@@ -129,6 +129,11 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx 
*pipe_ctx, struct spl
        populate_spltaps_from_taps(&spl_in->scaling_quality, 
&plane_state->scaling_quality);
        // Translate edge adaptive scaler preference
        spl_in->prefer_easf = pipe_ctx->stream->ctx->dc->config.prefer_easf;
+       spl_in->disable_easf = false;
+       if (pipe_ctx->stream->ctx->dc->debug.force_easf == 1)
+               spl_in->prefer_easf = false;
+       else if (pipe_ctx->stream->ctx->dc->debug.force_easf == 2)
+               spl_in->disable_easf = true;
        // Translate adaptive sharpening preference
        spl_in->adaptive_sharpness.enable = plane_state->adaptive_sharpness_en;
        if (plane_state->sharpnessX1000 == 0)   {
@@ -141,13 +146,19 @@ void translate_SPL_in_params_from_pipe_ctx(struct 
pipe_ctx *pipe_ctx, struct spl
                spl_in->adaptive_sharpness.sharpness = SHARPNESS_HIGH;
        }
        // Translate linear light scaling preference
-       spl_in->lls_pref = plane_state->linear_light_scaling;
-
+       if (pipe_ctx->stream->ctx->dc->debug.force_lls > 0)
+               spl_in->lls_pref = pipe_ctx->stream->ctx->dc->debug.force_lls;
+       else
+               spl_in->lls_pref = plane_state->linear_light_scaling;
        /* Translate chroma subsampling offset ( cositing ) */
        if (pipe_ctx->stream->ctx->dc->debug.force_cositing)
                spl_in->basic_in.cositing = 
pipe_ctx->stream->ctx->dc->debug.force_cositing - 1;
        else
                spl_in->basic_in.cositing = plane_state->cositing;
+       /* Translate transfer function */
+       spl_in->basic_in.tf_type = (enum spl_transfer_func_type) 
plane_state->in_transfer_func.type;
+       spl_in->basic_in.tf_predefined_type = (enum 
spl_transfer_func_predefined) plane_state->in_transfer_func.tf;
+
 }
 
 /// @brief Translate SPL output parameters to pipe context
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h 
b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h
index 7ab657ad3a20..1aaae7a5bd41 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h
@@ -373,7 +373,11 @@
        TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_SLOPE_P, 
mask_sh), \
        TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_EN_N, 
mask_sh), \
        TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_PIVOT_N, 
mask_sh), \
-       TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_SLOPE_N, 
mask_sh)
+       TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_SLOPE_N, 
mask_sh), \
+       TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_FRAC_BOT, mask_sh),\
+       TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_INT_BOT, mask_sh),\
+       TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_FRAC_BOT_C, 
mask_sh),\
+       TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh)
 
 #define DPP_REG_FIELD_LIST_DCN401(type) \
        DPP_REG_FIELD_LIST_DCN3(type); \
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c 
b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
index d9a08cd160b3..4b1e52803c7a 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
@@ -294,7 +294,7 @@ static void dpp401_dscl_set_scl_filter(
        const uint16_t *filter_h_c = NULL;
        const uint16_t *filter_v_c = NULL;
 
-       if (dpp->base.ctx->dc->config.use_spl)  {
+       if ((dpp->base.ctx->dc->config.use_spl) && 
(!dpp->base.ctx->dc->debug.disable_spl)) {
                filter_h = scl_data->dscl_prog_data.filter_h;
                filter_v = scl_data->dscl_prog_data.filter_v;
                filter_h_c = scl_data->dscl_prog_data.filter_h_c;
@@ -523,7 +523,7 @@ static void dpp401_dscl_set_manual_ratio_init(
 {
        uint32_t init_frac = 0;
        uint32_t init_int = 0;
-       if (dpp->base.ctx->dc->config.use_spl)  {
+       if ((dpp->base.ctx->dc->config.use_spl) && 
(!dpp->base.ctx->dc->debug.disable_spl)) {
                REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
                        SCL_H_SCALE_RATIO, 
data->dscl_prog_data.ratios.h_scale_ratio);
 
@@ -669,7 +669,7 @@ static void dpp401_dscl_program_easf(struct dpp *dpp_base, 
const struct scaler_d
                        SCL_SC_MATRIX_MODE, 
scl_data->dscl_prog_data.easf_matrix_mode);
        REG_UPDATE(DSCL_SC_MODE,
                        SCL_SC_LTONL_EN, 
scl_data->dscl_prog_data.easf_ltonl_en);
-       // DSCL_EASF_V_MODE
+       /* DSCL_EASF_V_MODE */
        REG_UPDATE(DSCL_EASF_V_MODE,
                        SCL_EASF_V_EN, scl_data->dscl_prog_data.easf_v_en);
        REG_UPDATE(DSCL_EASF_V_MODE,
@@ -716,7 +716,87 @@ static void dpp401_dscl_program_easf(struct dpp *dpp_base, 
const struct scaler_d
                        SCL_EASF_V_BF_MINA, 
scl_data->dscl_prog_data.easf_v_bf_mina);
        REG_UPDATE(DSCL_EASF_V_BF_FINAL_MAX_MIN,
                        SCL_EASF_V_BF_MINB, 
scl_data->dscl_prog_data.easf_v_bf_minb);
-       // DSCL_EASF_H_MODE
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG0,
+                       SCL_EASF_V_BF1_PWL_IN_SEG0, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg0);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG0,
+                       SCL_EASF_V_BF1_PWL_BASE_SEG0, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg0);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG0,
+                       SCL_EASF_V_BF1_PWL_SLOPE_SEG0, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg0);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG1,
+                       SCL_EASF_V_BF1_PWL_IN_SEG1, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg1);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG1,
+                       SCL_EASF_V_BF1_PWL_BASE_SEG1, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg1);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG1,
+                       SCL_EASF_V_BF1_PWL_SLOPE_SEG1, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg1);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG2,
+                       SCL_EASF_V_BF1_PWL_IN_SEG2, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg2);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG2,
+                       SCL_EASF_V_BF1_PWL_BASE_SEG2, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg2);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG2,
+                       SCL_EASF_V_BF1_PWL_SLOPE_SEG2, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg2);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG3,
+                       SCL_EASF_V_BF1_PWL_IN_SEG3, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg3);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG3,
+                       SCL_EASF_V_BF1_PWL_BASE_SEG3, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg3);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG3,
+                       SCL_EASF_V_BF1_PWL_SLOPE_SEG3, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg3);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG4,
+                       SCL_EASF_V_BF1_PWL_IN_SEG4, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg4);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG4,
+                       SCL_EASF_V_BF1_PWL_BASE_SEG4, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg4);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG4,
+                       SCL_EASF_V_BF1_PWL_SLOPE_SEG4, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg4);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG5,
+                       SCL_EASF_V_BF1_PWL_IN_SEG5, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg5);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG5,
+                       SCL_EASF_V_BF1_PWL_BASE_SEG5, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg5);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG5,
+                       SCL_EASF_V_BF1_PWL_SLOPE_SEG5, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg5);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG6,
+                       SCL_EASF_V_BF1_PWL_IN_SEG6, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg6);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG6,
+                       SCL_EASF_V_BF1_PWL_BASE_SEG6, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg6);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG6,
+                       SCL_EASF_V_BF1_PWL_SLOPE_SEG6, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg6);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG7,
+                       SCL_EASF_V_BF1_PWL_IN_SEG7, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg7);
+       REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG7,
+                       SCL_EASF_V_BF1_PWL_BASE_SEG7, 
scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg7);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG0,
+                       SCL_EASF_V_BF3_PWL_IN_SEG0, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_in_set0);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG0,
+                       SCL_EASF_V_BF3_PWL_BASE_SEG0, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_base_set0);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG0,
+                       SCL_EASF_V_BF3_PWL_SLOPE_SEG0, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_slope_set0);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG1,
+                       SCL_EASF_V_BF3_PWL_IN_SEG1, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_in_set1);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG1,
+                       SCL_EASF_V_BF3_PWL_BASE_SEG1, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_base_set1);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG1,
+                       SCL_EASF_V_BF3_PWL_SLOPE_SEG1, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_slope_set1);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG2,
+                       SCL_EASF_V_BF3_PWL_IN_SEG2, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_in_set2);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG2,
+                       SCL_EASF_V_BF3_PWL_BASE_SEG2, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_base_set2);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG2,
+                       SCL_EASF_V_BF3_PWL_SLOPE_SEG2, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_slope_set2);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG3,
+                       SCL_EASF_V_BF3_PWL_IN_SEG3, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_in_set3);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG3,
+                       SCL_EASF_V_BF3_PWL_BASE_SEG3, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_base_set3);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG3,
+                       SCL_EASF_V_BF3_PWL_SLOPE_SEG3, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_slope_set3);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG4,
+                       SCL_EASF_V_BF3_PWL_IN_SEG4, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_in_set4);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG4,
+                       SCL_EASF_V_BF3_PWL_BASE_SEG4, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_base_set4);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG4,
+                       SCL_EASF_V_BF3_PWL_SLOPE_SEG4, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_slope_set4);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG5,
+                       SCL_EASF_V_BF3_PWL_IN_SEG5, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_in_set5);
+       REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG5,
+                       SCL_EASF_V_BF3_PWL_BASE_SEG5, 
scl_data->dscl_prog_data.easf_v_bf3_pwl_base_set5);
+       /* DSCL_EASF_H_MODE */
        REG_UPDATE(DSCL_EASF_H_MODE,
                        SCL_EASF_H_EN, scl_data->dscl_prog_data.easf_h_en);
        REG_UPDATE(DSCL_EASF_H_MODE,
@@ -751,6 +831,117 @@ static void dpp401_dscl_program_easf(struct dpp 
*dpp_base, const struct scaler_d
                        SCL_EASF_H_BF_MINA, 
scl_data->dscl_prog_data.easf_h_bf_mina);
        REG_UPDATE(DSCL_EASF_H_BF_FINAL_MAX_MIN,
                        SCL_EASF_H_BF_MINB, 
scl_data->dscl_prog_data.easf_h_bf_minb);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG0,
+                       SCL_EASF_H_BF1_PWL_IN_SEG0, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg0);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG0,
+                       SCL_EASF_H_BF1_PWL_BASE_SEG0, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg0);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG0,
+                       SCL_EASF_H_BF1_PWL_SLOPE_SEG0, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg0);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG1,
+                       SCL_EASF_H_BF1_PWL_IN_SEG1, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg1);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG1,
+                       SCL_EASF_H_BF1_PWL_BASE_SEG1, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg1);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG1,
+                       SCL_EASF_H_BF1_PWL_SLOPE_SEG1, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg1);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG2,
+                       SCL_EASF_H_BF1_PWL_IN_SEG2, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg2);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG2,
+                       SCL_EASF_H_BF1_PWL_BASE_SEG2, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg2);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG2,
+                       SCL_EASF_H_BF1_PWL_SLOPE_SEG2, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg2);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG3,
+                       SCL_EASF_H_BF1_PWL_IN_SEG3, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg3);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG3,
+                       SCL_EASF_H_BF1_PWL_BASE_SEG3, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg3);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG3,
+                       SCL_EASF_H_BF1_PWL_SLOPE_SEG3, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg3);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG4,
+                       SCL_EASF_H_BF1_PWL_IN_SEG4, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg4);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG4,
+                       SCL_EASF_H_BF1_PWL_BASE_SEG4, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg4);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG4,
+                       SCL_EASF_H_BF1_PWL_SLOPE_SEG4, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg4);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG5,
+                       SCL_EASF_H_BF1_PWL_IN_SEG5, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg5);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG5,
+                       SCL_EASF_H_BF1_PWL_BASE_SEG5, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg5);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG5,
+                       SCL_EASF_H_BF1_PWL_SLOPE_SEG5, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg5);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG6,
+                       SCL_EASF_H_BF1_PWL_IN_SEG6, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg6);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG6,
+                       SCL_EASF_H_BF1_PWL_BASE_SEG6, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg6);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG6,
+                       SCL_EASF_H_BF1_PWL_SLOPE_SEG6, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg6);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG7,
+                       SCL_EASF_H_BF1_PWL_IN_SEG7, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg7);
+       REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG7,
+                       SCL_EASF_H_BF1_PWL_BASE_SEG7, 
scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg7);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG0,
+                       SCL_EASF_H_BF3_PWL_IN_SEG0, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_in_set0);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG0,
+                       SCL_EASF_H_BF3_PWL_BASE_SEG0, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_base_set0);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG0,
+                       SCL_EASF_H_BF3_PWL_SLOPE_SEG0, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_slope_set0);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG1,
+                       SCL_EASF_H_BF3_PWL_IN_SEG1, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_in_set1);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG1,
+                       SCL_EASF_H_BF3_PWL_BASE_SEG1, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_base_set1);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG1,
+                       SCL_EASF_H_BF3_PWL_SLOPE_SEG1, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_slope_set1);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG2,
+                       SCL_EASF_H_BF3_PWL_IN_SEG2, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_in_set2);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG2,
+                       SCL_EASF_H_BF3_PWL_BASE_SEG2, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_base_set2);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG2,
+                       SCL_EASF_H_BF3_PWL_SLOPE_SEG2, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_slope_set2);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG3,
+                       SCL_EASF_H_BF3_PWL_IN_SEG3, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_in_set3);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG3,
+                       SCL_EASF_H_BF3_PWL_BASE_SEG3, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_base_set3);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG3,
+                       SCL_EASF_H_BF3_PWL_SLOPE_SEG3, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_slope_set3);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG4,
+                       SCL_EASF_H_BF3_PWL_IN_SEG4, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_in_set4);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG4,
+                       SCL_EASF_H_BF3_PWL_BASE_SEG4, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_base_set4);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG4,
+                       SCL_EASF_H_BF3_PWL_SLOPE_SEG4, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_slope_set4);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG5,
+                       SCL_EASF_H_BF3_PWL_IN_SEG5, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_in_set5);
+       REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG5,
+                       SCL_EASF_H_BF3_PWL_BASE_SEG5, 
scl_data->dscl_prog_data.easf_h_bf3_pwl_base_set5);
+       /* DSCL_EASF_SC_MATRIX_C0C1, DSCL_EASF_SC_MATRIX_C2C3 */
+       REG_UPDATE(DSCL_SC_MATRIX_C0C1,
+                       SCL_SC_MATRIX_C0, 
scl_data->dscl_prog_data.easf_matrix_c0);
+       REG_UPDATE(DSCL_SC_MATRIX_C0C1,
+                       SCL_SC_MATRIX_C1, 
scl_data->dscl_prog_data.easf_matrix_c1);
+       REG_UPDATE(DSCL_SC_MATRIX_C2C3,
+                       SCL_SC_MATRIX_C2, 
scl_data->dscl_prog_data.easf_matrix_c2);
+       REG_UPDATE(DSCL_SC_MATRIX_C2C3,
+                       SCL_SC_MATRIX_C3, 
scl_data->dscl_prog_data.easf_matrix_c3);
+       PERF_TRACE();
+}
+/**
+ * dpp401_dscl_disable_easf - Disable EASF when no scaling (1:1)
+ *
+ * @dpp_base: High level DPP struct
+ * @scl_data: scalaer_data info
+ *
+ * When we have 1:1 scaling, we need to disable EASF
+ *
+ */
+static void dpp401_dscl_disable_easf(struct dpp *dpp_base, const struct 
scaler_data *scl_data)
+{
+       struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
+
+       PERF_TRACE();
+       /* DSCL_EASF_V_MODE */
+       REG_UPDATE(DSCL_EASF_V_MODE,
+                       SCL_EASF_V_EN, scl_data->dscl_prog_data.easf_v_en);
+       /* DSCL_EASF_H_MODE */
+       REG_UPDATE(DSCL_EASF_H_MODE,
+                       SCL_EASF_H_EN, scl_data->dscl_prog_data.easf_h_en);
        PERF_TRACE();
 }
 static void dpp401_dscl_set_isharp_filter(
@@ -852,7 +1043,7 @@ void dpp401_dscl_set_scaler_manual_scale(struct dpp 
*dpp_base,
 
        dpp->scl_data = *scl_data;
 
-       if (dpp->base.ctx->dc->config.use_spl)  {
+       if ((dpp->base.ctx->dc->config.use_spl) && 
(!dpp->base.ctx->dc->debug.disable_spl)) {
                dscl_mode = (enum dscl_mode_sel) 
scl_data->dscl_prog_data.dscl_mode;
                rect = (struct rect *)&scl_data->dscl_prog_data.recout;
                mpc_width = scl_data->dscl_prog_data.mpc_size.width;
@@ -900,8 +1091,12 @@ void dpp401_dscl_set_scaler_manual_scale(struct dpp 
*dpp_base,
        lb_config =  dpp401_dscl_find_lb_memory_config(dpp, scl_data);
        dpp401_dscl_set_lb(dpp, &scl_data->lb_params, lb_config);
 
-       if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS)
+       if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) {
+               if (dpp->base.ctx->dc->config.prefer_easf)
+                       dpp401_dscl_disable_easf(dpp_base, scl_data);
+               dpp401_dscl_program_isharp(dpp_base, scl_data);
                return;
+       }
 
        /* Black offsets */
        if (REG(SCL_BLACK_OFFSET)) {
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c 
b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
index a55421363772..fc43e7b5ec90 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
@@ -1845,6 +1845,7 @@ static bool dcn401_resource_construct(
        dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
        dc->caps.color.mpc.ocsc = 1;
        dc->config.use_spl = true;
+       dc->config.prefer_easf = true;
        dc->config.dc_mode_clk_limit_support = true;
        dc->config.enable_windowed_mpo_odm = true;
        /* read VBIOS LTTPR caps */
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h 
b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
index 5d5e01903ca1..a638c410e32a 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
@@ -342,7 +342,53 @@ bool dcn401_validate_bandwidth(struct dc *dc,
        SRI_ARR(OBUF_MEM_PWR_CTRL, DSCL, id),                                   
 \
        SRI_ARR(DSCL_MEM_PWR_STATUS, DSCL, id),                                 
 \
        SRI_ARR(DSCL_MEM_PWR_CTRL, DSCL, id),                                   
 \
-       SRI_ARR(DSCL_CONTROL, DSCL, id)
+       SRI_ARR(DSCL_CONTROL, DSCL, id),                                        
 \
+       SRI_ARR(DSCL_SC_MODE, DSCL, id),                                        
 \
+       SRI_ARR(DSCL_EASF_H_MODE, DSCL, id),                                    
 \
+       SRI_ARR(DSCL_EASF_H_BF_CNTL, DSCL, id),                                 
 \
+       SRI_ARR(DSCL_EASF_H_RINGEST_EVENTAP_REDUCE, DSCL, id),                  
 \
+       SRI_ARR(DSCL_EASF_H_RINGEST_EVENTAP_GAIN, DSCL, id),                    
 \
+       SRI_ARR(DSCL_EASF_H_BF_FINAL_MAX_MIN, DSCL, id),                        
 \
+       SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG0, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG1, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG2, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG3, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG4, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG5, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG6, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG7, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG0, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG1, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG2, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG3, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG4, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG5, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_MODE, DSCL, id),                                    
 \
+       SRI_ARR(DSCL_EASF_V_BF_CNTL, DSCL, id),                                 
 \
+       SRI_ARR(DSCL_EASF_V_RINGEST_3TAP_CNTL1, DSCL, id),                      
 \
+       SRI_ARR(DSCL_EASF_V_RINGEST_3TAP_CNTL2, DSCL, id),                      
 \
+       SRI_ARR(DSCL_EASF_V_RINGEST_3TAP_CNTL3, DSCL, id),                      
 \
+       SRI_ARR(DSCL_EASF_V_RINGEST_EVENTAP_REDUCE, DSCL, id),                  
 \
+       SRI_ARR(DSCL_EASF_V_RINGEST_EVENTAP_GAIN, DSCL, id),                    
 \
+       SRI_ARR(DSCL_EASF_V_BF_FINAL_MAX_MIN, DSCL, id),                        
 \
+       SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG0, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG1, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG2, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG3, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG4, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG5, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG6, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG7, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG0, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG1, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG2, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG3, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG4, DSCL, id),                            
 \
+       SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG5, DSCL, id),                            
 \
+       SRI_ARR(DSCL_SC_MATRIX_C0C1, DSCL, id),                                 
 \
+       SRI_ARR(DSCL_SC_MATRIX_C2C3, DSCL, id),                                 
 \
+       SRI_ARR(SCL_VERT_FILTER_INIT_BOT, DSCL, id),                            
 \
+       SRI_ARR(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id)
 
 /* OPP */
 #define OPP_REG_LIST_DCN401_RI(id)                                             
 \
diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c 
b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
index 542cd6cdef46..82fbd2b59c70 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
+++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
@@ -324,14 +324,18 @@ static void spl_calculate_recout(struct spl_in *spl_in, 
struct spl_out *spl_out)
        overlapping_area = intersect_rec(&mpc_slice_of_plane_clip, &odm_slice);
 
        if (overlapping_area.height > 0 &&
-                       overlapping_area.width > 0)
+                       overlapping_area.width > 0) {
                /* shift the overlapping area so it is with respect to current
                 * ODM slice's position
                 */
                spl_out->scl_data.recout = shift_rec(
                                &overlapping_area,
                                -odm_slice.x, -odm_slice.y);
-       else
+               spl_out->scl_data.recout.height -=
+                       spl_in->debug.visual_confirm_base_offset;
+               spl_out->scl_data.recout.height -=
+                       spl_in->debug.visual_confirm_dpp_offset;
+       } else
                /* if there is no overlap, zero recout */
                memset(&spl_out->scl_data.recout, 0,
                                sizeof(struct spl_rect));
@@ -493,13 +497,11 @@ static void spl_calculate_init_and_vp(bool flip_scan_dir,
 
 static bool spl_is_yuv420(enum spl_pixel_format format)
 {
-       switch (format) {
-       case SPL_PIXEL_FORMAT_420BPP8:
-       case SPL_PIXEL_FORMAT_420BPP10:
+       if ((format >= SPL_PIXEL_FORMAT_VIDEO_BEGIN) &&
+               (format <= SPL_PIXEL_FORMAT_VIDEO_END))
                return true;
-       default:
-               return false;
-       }
+
+       return false;
 }
 
 /*Calculate inits and viewport */
@@ -969,12 +971,17 @@ static bool enable_easf(int scale_ratio, int taps,
 }
 /* Set EASF data */
 static void spl_set_easf_data(struct dscl_prog_data *dscl_prog_data,
-       bool enable_easf_v, bool enable_easf_h, enum linear_light_scaling 
lls_pref)
+       bool enable_easf_v, bool enable_easf_h, enum linear_light_scaling 
lls_pref,
+       enum spl_pixel_format format)
 {
-       dscl_prog_data->easf_matrix_mode = 0;
+       if (spl_is_yuv420(format)) /* TODO: 0 = RGB, 1 = YUV */
+               dscl_prog_data->easf_matrix_mode = 1;
+       else
+               dscl_prog_data->easf_matrix_mode = 0;
+
        if (enable_easf_v) {
                dscl_prog_data->easf_v_en = true;
-               dscl_prog_data->easf_v_ring = 1;
+               dscl_prog_data->easf_v_ring = 0;
                dscl_prog_data->easf_v_sharp_factor = 1;
                dscl_prog_data->easf_v_bf1_en = 1;      // 1-bit, BF1 
calculation enable, 0=disable, 1=enable
                dscl_prog_data->easf_v_bf2_mode = 0xF;  // 4-bit, BF2 
calculation mode
@@ -1081,10 +1088,12 @@ static void spl_set_easf_data(struct dscl_prog_data 
*dscl_prog_data,
                                0x0780; // FP0.6.6, BF3 Input value PWL Segment 
5 (0.5)
                        dscl_prog_data->easf_v_bf3_pwl_base_set5 = -63; // 
S0.6, BF3 Base PWL Segment 5
                }
-       }
+       } else
+               dscl_prog_data->easf_v_en = false;
+
        if (enable_easf_h) {
                dscl_prog_data->easf_h_en = true;
-               dscl_prog_data->easf_h_ring = 1;
+               dscl_prog_data->easf_h_ring = 0;
                dscl_prog_data->easf_h_sharp_factor = 1;
                dscl_prog_data->easf_h_bf1_en =
                        1;      // 1-bit, BF1 calculation enable, 0=disable, 
1=enable
@@ -1177,7 +1186,9 @@ static void spl_set_easf_data(struct dscl_prog_data 
*dscl_prog_data,
                                0x0780; // FP0.6.6, BF3 Input value PWL Segment 
5 (0.5)
                        dscl_prog_data->easf_h_bf3_pwl_base_set5 = -63; // 
S0.6, BF3 Base PWL Segment 5
                } // if (lls_pref == LLS_PREF_YES)
-       }
+       } else
+               dscl_prog_data->easf_h_en = false;
+
        if (lls_pref == LLS_PREF_YES)   {
                dscl_prog_data->easf_ltonl_en = 1;      // Linear input
                dscl_prog_data->easf_matrix_c0 =
@@ -1304,12 +1315,40 @@ static bool spl_get_isharp_en(struct adaptive_sharpness 
adp_sharpness,
        }
        return enable_isharp;
 }
+
+static bool spl_choose_lls_policy(enum spl_pixel_format format,
+       enum spl_transfer_func_type tf_type,
+       enum spl_transfer_func_predefined tf_predefined_type,
+       enum linear_light_scaling *lls_pref)
+{
+       if (spl_is_yuv420(format)) {
+               *lls_pref = LLS_PREF_NO;
+               if ((tf_type == SPL_TF_TYPE_PREDEFINED) || (tf_type == 
SPL_TF_TYPE_DISTRIBUTED_POINTS))
+                       return true;
+       } else { /* RGB or YUV444 */
+               if (tf_type == SPL_TF_TYPE_PREDEFINED) {
+                       if ((tf_predefined_type == SPL_TRANSFER_FUNCTION_HLG) ||
+                               (tf_predefined_type == 
SPL_TRANSFER_FUNCTION_HLG12))
+                               *lls_pref = LLS_PREF_NO;
+                       else
+                               *lls_pref = LLS_PREF_YES;
+                       return true;
+               } else if (tf_type == SPL_TF_TYPE_BYPASS) {
+                       *lls_pref = LLS_PREF_YES;
+                       return true;
+               }
+       }
+       *lls_pref = LLS_PREF_NO;
+       return false;
+}
+
 /* Caclulate scaler parameters */
 bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out 
*spl_out)
 {
        bool res = false;
        bool enable_easf_v = false;
        bool enable_easf_h = false;
+       bool lls_enable_easf = true;
        // All SPL calls
        /* recout calculation */
        /* depends on h_active */
@@ -1335,17 +1374,33 @@ bool spl_calculate_scaler_params(struct spl_in *spl_in, 
struct spl_out *spl_out)
 
        if (!res)
                return res;
+
+       /*
+        * If lls_pref is LLS_PREF_DONT_CARE, then use pixel format and transfer
+        *  function to determine whether to use LINEAR or NONLINEAR scaling
+        */
+       if (spl_in->lls_pref == LLS_PREF_DONT_CARE)
+               lls_enable_easf = spl_choose_lls_policy(spl_in->basic_in.format,
+                       spl_in->basic_in.tf_type, 
spl_in->basic_in.tf_predefined_type,
+                       &spl_in->lls_pref);
+
        // Save all calculated parameters in dscl_prog_data structure to 
program hw registers
        spl_set_dscl_prog_data(spl_in, spl_out);
-       // Enable EASF on vertical?
+
        int vratio = dc_fixpt_ceil(spl_out->scl_data.ratios.vert);
        int hratio = dc_fixpt_ceil(spl_out->scl_data.ratios.horz);
-       enable_easf_v = enable_easf(vratio, spl_out->scl_data.taps.v_taps, 
spl_in->lls_pref, spl_in->prefer_easf);
-       // Enable EASF on horizontal?
-       enable_easf_h = enable_easf(hratio, spl_out->scl_data.taps.h_taps, 
spl_in->lls_pref, spl_in->prefer_easf);
+       if (!lls_enable_easf || spl_in->disable_easf) {
+               enable_easf_v = false;
+               enable_easf_h = false;
+       } else {
+               /* Enable EASF on vertical? */
+               enable_easf_v = enable_easf(vratio, 
spl_out->scl_data.taps.v_taps, spl_in->lls_pref, spl_in->prefer_easf);
+               /* Enable EASF on horizontal? */
+               enable_easf_h = enable_easf(hratio, 
spl_out->scl_data.taps.h_taps, spl_in->lls_pref, spl_in->prefer_easf);
+       }
        // Set EASF
-       spl_set_easf_data(spl_out->dscl_prog_data, enable_easf_v, 
enable_easf_h, spl_in->lls_pref);
-       // Set iSHARP
+       spl_set_easf_data(spl_out->dscl_prog_data, enable_easf_v, 
enable_easf_h, spl_in->lls_pref,
+               spl_in->basic_in.format);       // Set iSHARP
        bool enable_isharp = spl_get_isharp_en(spl_in->adaptive_sharpness, 
vratio, hratio,
                                                                
spl_out->scl_data.taps);
        if (enable_isharp)
diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h 
b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h
index c5ef15f16c68..0c9edee0582e 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h
+++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h
@@ -132,6 +132,26 @@ struct spl_scaler_data {
        struct spl_inits inits;
 };
 
+enum spl_transfer_func_type {
+       SPL_TF_TYPE_PREDEFINED,
+       SPL_TF_TYPE_DISTRIBUTED_POINTS,
+       SPL_TF_TYPE_BYPASS,
+       SPL_TF_TYPE_HWPWL
+};
+
+enum spl_transfer_func_predefined {
+       SPL_TRANSFER_FUNCTION_SRGB,
+       SPL_TRANSFER_FUNCTION_BT709,
+       SPL_TRANSFER_FUNCTION_PQ,
+       SPL_TRANSFER_FUNCTION_LINEAR,
+       SPL_TRANSFER_FUNCTION_UNITY,
+       SPL_TRANSFER_FUNCTION_HLG,
+       SPL_TRANSFER_FUNCTION_HLG12,
+       SPL_TRANSFER_FUNCTION_GAMMA22,
+       SPL_TRANSFER_FUNCTION_GAMMA24,
+       SPL_TRANSFER_FUNCTION_GAMMA26
+};
+
 /*==============================================================*/
 /* Below structs are defined to hold hw register data */
 
@@ -400,7 +420,8 @@ struct basic_in     {
        int mpc_combine_h; // MPC Horizontal Combine Factor (split_count)
        int mpc_combine_v; // MPC Vertical Combine Factor (split_idx)
        // Inputs for adaptive scaler - TODO
-       // struct dc_transfer_func transfer_func;       //      Transfer 
function
+       enum spl_transfer_func_type tf_type; /* Transfer function type */
+       enum spl_transfer_func_predefined tf_predefined_type; /* Transfer 
function predefined type */
        // enum dc_transfer_func_predefined tf;
        enum spl_color_space color_space;       //      Color Space
        unsigned int max_luminance;     //      Max Luminance TODO: Is 
determined in dc_hw_sequencer.c is_sdr
@@ -441,6 +462,11 @@ struct spl_funcs   {
                int *num_part_c);
 };
 
+struct spl_debug {
+       int visual_confirm_base_offset;
+       int visual_confirm_dpp_offset;
+};
+
 struct spl_in  {
        struct basic_out basic_out;
        struct basic_in basic_in;
@@ -452,6 +478,8 @@ struct spl_in       {
        struct adaptive_sharpness adaptive_sharpness;   //      Adaptive 
Sharpness
        enum linear_light_scaling lls_pref;     //      Linear Light Scaling
        bool prefer_easf;
+       bool disable_easf;
+       struct spl_debug debug;
 };
 // end of SPL inputs
 
-- 
2.34.1

Reply via email to