From: Alvin Lee <[email protected]>

[Description]
- UPSP should only be enabled when we want linear scaling for 420/422
- In DC for non-FP16 formats that are told to scale in non-linear, program
  bypass for PRE_GAM since these formats are already non-linear (i.e.,
  YUV420, YUV422, RGB, etc.)

Reviewed-by: Aric Cyr <[email protected]>
Reviewed-by: Taimur Hassan <[email protected]>
Signed-off-by: Alvin Lee <[email protected]>
Signed-off-by: Chenyu Chen <[email protected]>
---
 .../gpu/drm/amd/display/dc/core/dc_resource.c | 18 ++++++++++++----
 .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c  | 20 +++++++++++++-----
 .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h  |  3 ++-
 .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c   | 21 ++++++++++++++++++-
 drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h   |  3 ++-
 drivers/gpu/drm/amd/display/dc/inc/resource.h |  3 ++-
 6 files changed, 55 insertions(+), 13 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 f9b8e9474b4c..593c1fd537ae 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1557,11 +1557,21 @@ void resource_build_test_pattern_params(struct 
resource_context *res_ctx,
        }
 }
 
-enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format)
+enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format,
+               enum dc_scaling_linearity scaling_linearity)
 {
-       if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN && format <= 
SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb) //420 Formats
+       bool scaling_in_linear = (scaling_linearity == 
DC_SCALING_LINEARITY_LINEAR);
+       bool is_420_format = (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN &&
+                       format <= SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb);
+       bool is_422_format = (format > 
SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb &&
+                       format < SURFACE_PIXEL_FORMAT_SUBSAMPLE_END);
+
+       /* UPSP (chroma upsampling) is only needed when subsampled YUV is 
scaled in
+        * linear space.
+        */
+       if (scaling_in_linear && is_420_format)
                return UPSP_HORIZONTAL_VERTICAL_UPSAMPLING;
-       if (format > SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb && format < 
SURFACE_PIXEL_FORMAT_SUBSAMPLE_END) //422 Formats
+       if (scaling_in_linear && is_422_format)
                return UPSP_HORIZONTAL_UPSAMPLING_ONLY;
        return UPSP_BYPASS;
 }
@@ -1611,7 +1621,7 @@ bool resource_build_scaling_params(struct pipe_ctx 
*pipe_ctx)
                        pipe_ctx->plane_res.scl_data.lb_params.depth = 
LB_PIXEL_DEPTH_30BPP;
 
                pipe_ctx->plane_res.scl_data.lb_params.alpha_en = 
plane_state->per_pixel_alpha;
-               pipe_ctx->plane_res.scl_data.upsp = 
resource_is_upsp_required(plane_state->format);
+               pipe_ctx->plane_res.scl_data.upsp = 
resource_is_upsp_required(plane_state->format, plane_state->scaling_linearity);
 
                // Convert pipe_ctx to respective input params for SPL
                translate_SPL_in_params_from_pipe_ctx(pipe_ctx, spl_in);
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c 
b/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c
index 04cab7d3a5c2..38739ed048fa 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c
@@ -25,17 +25,27 @@
 void dpp50_set_pregam_state(
        struct dpp *dpp_base,
        enum dc_transfer_func_predefined tr,
-       enum dc_scaling_linearity scaling)
+       enum dc_scaling_linearity scaling,
+       bool source_is_linear)
 {
        struct dcn50_dpp *dpp = TO_DCN50_DPP(dpp_base);
        enum pregam_mode pre_degam_en = PREGAM_DEGAM;
        enum degam_lut degamma_lut_selection = 0;
 
        if (scaling == DC_SCALING_LINEARITY_SOURCE) {
-               //If scaling in non-linear, apply regamma
-               REG_SET_2(PRE_GAM, 0,
-                       PRE_GAM_MODE, PREGAM_REGAM,
-                       PRE_REGAM_SELECT, REGAM_20);
+               if (source_is_linear) {
+                       //Linear source data (e.g. FP16) must be de-linearized
+                       //(apply regamma) before scaling in source/non-linear 
space.
+                       REG_SET_2(PRE_GAM, 0,
+                               PRE_GAM_MODE, PREGAM_REGAM,
+                               PRE_REGAM_SELECT, REGAM_20);
+               } else {
+                       //Non-linear source data (e.g. YUV) is already in source
+                       //space, so scale directly with no pregam conversion.
+                       REG_SET_2(PRE_GAM, 0,
+                               PRE_GAM_MODE, PREGAM_BYPASS,
+                               PRE_DEGAM_SELECT, 0);
+               }
        } else {
                //If scaling in linear, apply degamma based on TF
                switch (tr) {
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h 
b/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h
index 7f5d3fa6bbef..c81e910ae095 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h
@@ -82,6 +82,7 @@ void dpp50_dpp_setup(
 void dpp50_set_pregam_state(
        struct dpp *dpp_base,
        enum dc_transfer_func_predefined tr,
-       enum dc_scaling_linearity scaling);
+       enum dc_scaling_linearity scaling,
+       bool source_is_linear);
 
 #endif /* __DCN50_DPP_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index 79be5c385280..430966af3808 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -528,6 +528,24 @@ bool dcn32_set_mcm_luts(struct dc *dc, struct dpp *dpp, 
struct hubp *hubp,
        return result;
 }
 
+/*
+ * FP16 / 64bpp 16161616 surfaces store pixel data in linear light. These are
+ * the only source formats that must be de-linearized before scaling in
+ * source/non-linear space; every other format is already non-linear.
+ */
+static bool is_source_pixel_format_linear(enum surface_pixel_format format)
+{
+       switch (format) {
+       case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
+       case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
+       case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
+       case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
+               return true;
+       default:
+               return false;
+       }
+}
+
 bool dcn32_set_input_transfer_func(struct set_input_transfer_func_params 
*params)
 {
        struct dce_hwseq *hws = params->dc->hwseq;
@@ -547,7 +565,8 @@ bool dcn32_set_input_transfer_func(struct 
set_input_transfer_func_params *params
                tf = plane_state->in_transfer_func.tf;
 
        if (dpp->funcs->dpp_set_pregam_state)
-               dpp->funcs->dpp_set_pregam_state(dpp, tf, 
plane_state->scaling_linearity);
+               dpp->funcs->dpp_set_pregam_state(dpp, tf, 
plane_state->scaling_linearity,
+                               
is_source_pixel_format_linear(plane_state->format));
        else
                dpp->funcs->dpp_set_pre_degam(dpp, tf);
 
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
index b31b144d2e8f..930b5533256f 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
@@ -378,7 +378,8 @@ struct dpp_funcs {
        void (*dpp_set_pregam_state)(
                        struct dpp *dpp_base,
                        enum dc_transfer_func_predefined tr,
-                       enum dc_scaling_linearity scaling);
+                       enum dc_scaling_linearity scaling,
+                       bool source_is_linear);
        void (*dpp_program_upsp)(
                        struct dpp *dpp_base,
                        const struct dscl_prog_data *dscl_prog_data);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h 
b/drivers/gpu/drm/amd/display/dc/inc/resource.h
index 8e21aaac06b3..9c6794f8dec0 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
@@ -123,7 +123,8 @@ void resource_build_test_pattern_params(
                struct resource_context *res_ctx,
                struct pipe_ctx *pipe_ctx);
 
-enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format);
+enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format,
+               enum dc_scaling_linearity scaling_linearity);
 
 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx);
 
-- 
2.43.0

Reply via email to