OSDN Git Service

drm/amd/display: separate scl functions out from dcn10_dpp
authorYue Hin Lau <Yuehin.Lau@amd.com>
Tue, 15 Aug 2017 21:44:19 +0000 (17:44 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 26 Sep 2017 22:16:51 +0000 (18:16 -0400)
Signed-off-by: Yue Hin Lau <Yuehin.Lau@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dcn10/Makefile
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c [new file with mode: 0644]

index 8af201a..83619e6 100644 (file)
@@ -3,7 +3,8 @@
 
 DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \
                dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \
-               dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o
+               dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o \
+               dcn10_dpp_dscl.o
 
 AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10))
 
index e52e1f4..a841ed3 100644 (file)
@@ -112,514 +112,6 @@ enum gamut_remap_select {
        GAMUT_REMAP_COMB_COEFF
 };
 
-static void dpp_set_overscan(
-       struct dcn10_dpp *xfm,
-       const struct scaler_data *data)
-{
-       uint32_t left = data->recout.x;
-       uint32_t top = data->recout.y;
-
-       int right = data->h_active - data->recout.x - data->recout.width;
-       int bottom = data->v_active - data->recout.y - data->recout.height;
-
-       if (right < 0) {
-               BREAK_TO_DEBUGGER();
-               right = 0;
-       }
-       if (bottom < 0) {
-               BREAK_TO_DEBUGGER();
-               bottom = 0;
-       }
-
-       REG_SET_2(DSCL_EXT_OVERSCAN_LEFT_RIGHT, 0,
-               EXT_OVERSCAN_LEFT, left,
-               EXT_OVERSCAN_RIGHT, right);
-
-       REG_SET_2(DSCL_EXT_OVERSCAN_TOP_BOTTOM, 0,
-               EXT_OVERSCAN_BOTTOM, bottom,
-               EXT_OVERSCAN_TOP, top);
-}
-
-static void dpp_set_otg_blank(
-               struct dcn10_dpp *xfm, const struct scaler_data *data)
-{
-       uint32_t h_blank_start = data->h_active;
-       uint32_t h_blank_end = 0;
-       uint32_t v_blank_start = data->v_active;
-       uint32_t v_blank_end = 0;
-
-       REG_SET_2(OTG_H_BLANK, 0,
-                       OTG_H_BLANK_START, h_blank_start,
-                       OTG_H_BLANK_END, h_blank_end);
-
-       REG_SET_2(OTG_V_BLANK, 0,
-                       OTG_V_BLANK_START, v_blank_start,
-                       OTG_V_BLANK_END, v_blank_end);
-}
-
-static enum dscl_mode_sel get_dscl_mode(
-               const struct scaler_data *data, bool dbg_always_scale)
-{
-       const long long one = dal_fixed31_32_one.value;
-       bool ycbcr = false;
-       bool format420 = false;
-
-       if (data->format == PIXEL_FORMAT_FP16)
-               return DSCL_MODE_DSCL_BYPASS;
-
-       if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN
-                       && data->format <= PIXEL_FORMAT_VIDEO_END)
-               ycbcr = true;
-
-       if (data->format == PIXEL_FORMAT_420BPP8 ||
-                       data->format == PIXEL_FORMAT_420BPP10)
-               format420 = true;
-
-       if (data->ratios.horz.value == one
-                       && data->ratios.vert.value == one
-                       && data->ratios.horz_c.value == one
-                       && data->ratios.vert_c.value == one
-                       && !dbg_always_scale)
-               return DSCL_MODE_SCALING_444_BYPASS;
-
-       if (!format420) {
-               if (ycbcr)
-                       return DSCL_MODE_SCALING_444_YCBCR_ENABLE;
-               else
-                       return DSCL_MODE_SCALING_444_RGB_ENABLE;
-       }
-       if (data->ratios.horz.value == one && data->ratios.vert.value == one)
-               return DSCL_MODE_SCALING_420_LUMA_BYPASS;
-       if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one)
-               return DSCL_MODE_SCALING_420_CHROMA_BYPASS;
-
-       return DSCL_MODE_SCALING_420_YCBCR_ENABLE;
-}
-
-static int get_pixel_depth_val(enum lb_pixel_depth depth)
-{
-       if (depth == LB_PIXEL_DEPTH_30BPP)
-               return 0; /* 10 bpc */
-       else if (depth == LB_PIXEL_DEPTH_24BPP)
-               return 1; /* 8 bpc */
-       else if (depth == LB_PIXEL_DEPTH_18BPP)
-               return 2; /* 6 bpc */
-       else if (depth == LB_PIXEL_DEPTH_36BPP)
-               return 3; /* 12 bpc */
-       else {
-               ASSERT(0);
-               return -1; /* Unsupported */
-       }
-}
-
-static void dpp_set_lb(
-       struct dcn10_dpp *xfm,
-       const struct line_buffer_params *lb_params,
-       enum lb_memory_config mem_size_config)
-{
-       uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth);
-       uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth;
-       REG_SET_7(LB_DATA_FORMAT, 0,
-               PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */
-               PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */
-               PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */
-               DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */
-               DITHER_EN, 0, /* Dithering enable: Disabled */
-               INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */
-               ALPHA_EN, lb_params->alpha_en); /* Alpha enable */
-
-       REG_SET_2(LB_MEMORY_CTRL, 0,
-               MEMORY_CONFIG, mem_size_config,
-               LB_MAX_PARTITIONS, 63);
-}
-
-static void dpp_set_scaler_filter(
-               struct dcn10_dpp *xfm,
-               uint32_t taps,
-               enum dcn10_coef_filter_type_sel filter_type,
-               const uint16_t *filter)
-{
-       const int tap_pairs = (taps + 1) / 2;
-       int phase;
-       int pair;
-       uint16_t odd_coef, even_coef;
-
-       REG_SET_3(SCL_COEF_RAM_TAP_SELECT, 0,
-               SCL_COEF_RAM_TAP_PAIR_IDX, 0,
-               SCL_COEF_RAM_PHASE, 0,
-               SCL_COEF_RAM_FILTER_TYPE, filter_type);
-
-       for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) {
-               for (pair = 0; pair < tap_pairs; pair++) {
-                       even_coef = filter[phase * taps + 2 * pair];
-                       if ((pair * 2 + 1) < taps)
-                               odd_coef = filter[phase * taps + 2 * pair + 1];
-                       else
-                               odd_coef = 0;
-
-                       REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0,
-                               /* Even tap coefficient (bits 1:0 fixed to 0) */
-                               SCL_COEF_RAM_EVEN_TAP_COEF, even_coef,
-                               /* Write/read control for even coefficient */
-                               SCL_COEF_RAM_EVEN_TAP_COEF_EN, 1,
-                               /* Odd tap coefficient (bits 1:0 fixed to 0) */
-                               SCL_COEF_RAM_ODD_TAP_COEF, odd_coef,
-                               /* Write/read control for odd coefficient */
-                               SCL_COEF_RAM_ODD_TAP_COEF_EN, 1);
-               }
-       }
-
-}
-
-#if 0
-bool dpp_set_pixel_storage_depth(
-       struct dpp *xfm,
-       enum lb_pixel_depth depth,
-       const struct bit_depth_reduction_params *bit_depth_params)
-{
-       struct dcn10_dpp *xfm110 = TO_DCN10_DPP(xfm);
-       bool ret = true;
-       uint32_t value;
-       enum dc_color_depth color_depth;
-
-       value = dm_read_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT));
-       switch (depth) {
-       case LB_PIXEL_DEPTH_18BPP:
-               color_depth = COLOR_DEPTH_666;
-               set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH);
-               set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
-               break;
-       case LB_PIXEL_DEPTH_24BPP:
-               color_depth = COLOR_DEPTH_888;
-               set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH);
-               set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
-               break;
-       case LB_PIXEL_DEPTH_30BPP:
-               color_depth = COLOR_DEPTH_101010;
-               set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH);
-               set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
-               break;
-       case LB_PIXEL_DEPTH_36BPP:
-               color_depth = COLOR_DEPTH_121212;
-               set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH);
-               set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
-               break;
-       default:
-               ret = false;
-               break;
-       }
-
-       if (ret == true) {
-               set_denormalization(xfm110, color_depth);
-               ret = program_bit_depth_reduction(xfm110, color_depth,
-                               bit_depth_params);
-
-               set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN);
-               dm_write_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value);
-               if (!(xfm110->lb_pixel_depth_supported & depth)) {
-                       /* We should use unsupported capabilities
-                        * unless it is required by w/a
-                        */
-                       dm_logger_write(xfm->ctx->logger, LOG_WARNING,
-                               "%s: Capability not supported",
-                               __func__);
-               }
-       }
-
-       return ret;
-}
-#endif
-
-static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio)
-{
-       if (taps == 8)
-               return get_filter_8tap_64p(ratio);
-       else if (taps == 7)
-               return get_filter_7tap_64p(ratio);
-       else if (taps == 6)
-               return get_filter_6tap_64p(ratio);
-       else if (taps == 5)
-               return get_filter_5tap_64p(ratio);
-       else if (taps == 4)
-               return get_filter_4tap_64p(ratio);
-       else if (taps == 3)
-               return get_filter_3tap_64p(ratio);
-       else if (taps == 2)
-               return filter_2tap_64p;
-       else if (taps == 1)
-               return NULL;
-       else {
-               /* should never happen, bug */
-               BREAK_TO_DEBUGGER();
-               return NULL;
-       }
-}
-
-static void dpp_set_scl_filter(
-               struct dcn10_dpp *xfm,
-               const struct scaler_data *scl_data,
-               bool chroma_coef_mode)
-{
-       bool h_2tap_hardcode_coef_en = false;
-       bool v_2tap_hardcode_coef_en = false;
-       bool h_2tap_sharp_en = false;
-       bool v_2tap_sharp_en = false;
-       uint32_t h_2tap_sharp_factor = scl_data->sharpness.horz;
-       uint32_t v_2tap_sharp_factor = scl_data->sharpness.vert;
-       bool coef_ram_current;
-       const uint16_t *filter_h = NULL;
-       const uint16_t *filter_v = NULL;
-       const uint16_t *filter_h_c = NULL;
-       const uint16_t *filter_v_c = NULL;
-
-       h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3
-                                       && scl_data->taps.h_taps_c < 3
-               && (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1);
-       v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3
-                                       && scl_data->taps.v_taps_c < 3
-               && (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1);
-
-       h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0;
-       v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0;
-
-       REG_UPDATE_6(DSCL_2TAP_CONTROL,
-               SCL_H_2TAP_HARDCODE_COEF_EN, h_2tap_hardcode_coef_en,
-               SCL_H_2TAP_SHARP_EN, h_2tap_sharp_en,
-               SCL_H_2TAP_SHARP_FACTOR, h_2tap_sharp_factor,
-               SCL_V_2TAP_HARDCODE_COEF_EN, v_2tap_hardcode_coef_en,
-               SCL_V_2TAP_SHARP_EN, v_2tap_sharp_en,
-               SCL_V_2TAP_SHARP_FACTOR, v_2tap_sharp_factor);
-
-       if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) {
-               bool filter_updated = false;
-
-               filter_h = get_filter_coeffs_64p(
-                               scl_data->taps.h_taps, scl_data->ratios.horz);
-               filter_v = get_filter_coeffs_64p(
-                               scl_data->taps.v_taps, scl_data->ratios.vert);
-
-               filter_updated = (filter_h && (filter_h != xfm->filter_h))
-                               || (filter_v && (filter_v != xfm->filter_v));
-
-               if (chroma_coef_mode) {
-                       filter_h_c = get_filter_coeffs_64p(
-                                       scl_data->taps.h_taps_c, scl_data->ratios.horz_c);
-                       filter_v_c = get_filter_coeffs_64p(
-                                       scl_data->taps.v_taps_c, scl_data->ratios.vert_c);
-                       filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c))
-                                                       || (filter_v_c && (filter_v_c != xfm->filter_v_c));
-               }
-
-               if (filter_updated) {
-                       uint32_t scl_mode = REG_READ(SCL_MODE);
-
-                       if (!h_2tap_hardcode_coef_en && filter_h) {
-                               dpp_set_scaler_filter(
-                                       xfm, scl_data->taps.h_taps,
-                                       SCL_COEF_LUMA_HORZ_FILTER, filter_h);
-                       }
-                       xfm->filter_h = filter_h;
-                       if (!v_2tap_hardcode_coef_en && filter_v) {
-                               dpp_set_scaler_filter(
-                                       xfm, scl_data->taps.v_taps,
-                                       SCL_COEF_LUMA_VERT_FILTER, filter_v);
-                       }
-                       xfm->filter_v = filter_v;
-                       if (chroma_coef_mode) {
-                               if (!h_2tap_hardcode_coef_en && filter_h_c) {
-                                       dpp_set_scaler_filter(
-                                               xfm, scl_data->taps.h_taps_c,
-                                               SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c);
-                               }
-                               if (!v_2tap_hardcode_coef_en && filter_v_c) {
-                                       dpp_set_scaler_filter(
-                                               xfm, scl_data->taps.v_taps_c,
-                                               SCL_COEF_CHROMA_VERT_FILTER, filter_v_c);
-                               }
-                       }
-                       xfm->filter_h_c = filter_h_c;
-                       xfm->filter_v_c = filter_v_c;
-
-                       coef_ram_current = get_reg_field_value_ex(
-                               scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT,
-                               xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT);
-
-                       /* Swap coefficient RAM and set chroma coefficient mode */
-                       REG_SET_2(SCL_MODE, scl_mode,
-                                       SCL_COEF_RAM_SELECT, !coef_ram_current,
-                                       SCL_CHROMA_COEF_MODE, chroma_coef_mode);
-               }
-       }
-}
-
-
-static int get_lb_depth_bpc(enum lb_pixel_depth depth)
-{
-       if (depth == LB_PIXEL_DEPTH_30BPP)
-               return 10;
-       else if (depth == LB_PIXEL_DEPTH_24BPP)
-               return 8;
-       else if (depth == LB_PIXEL_DEPTH_18BPP)
-               return 6;
-       else if (depth == LB_PIXEL_DEPTH_36BPP)
-               return 12;
-       else {
-               BREAK_TO_DEBUGGER();
-               return -1; /* Unsupported */
-       }
-}
-
-static void calc_lb_num_partitions(
-               const struct scaler_data *scl_data,
-               enum lb_memory_config lb_config,
-               int *num_part_y,
-               int *num_part_c)
-{
-       int line_size = scl_data->viewport.width < scl_data->recout.width ?
-                       scl_data->viewport.width : scl_data->recout.width;
-       int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ?
-                       scl_data->viewport_c.width : scl_data->recout.width;
-       int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth);
-       int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */
-       int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */
-       int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */
-       int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a;
-
-       if (lb_config == LB_MEMORY_CONFIG_1) {
-               lb_memory_size = 816;
-               lb_memory_size_c = 816;
-               lb_memory_size_a = 984;
-       } else if (lb_config == LB_MEMORY_CONFIG_2) {
-               lb_memory_size = 1088;
-               lb_memory_size_c = 1088;
-               lb_memory_size_a = 1312;
-       } else if (lb_config == LB_MEMORY_CONFIG_3) {
-               lb_memory_size = 816 + 1088 + 848 + 848 + 848;
-               lb_memory_size_c = 816 + 1088;
-               lb_memory_size_a = 984 + 1312 + 456;
-       } else {
-               lb_memory_size = 816 + 1088 + 848;
-               lb_memory_size_c = 816 + 1088 + 848;
-               lb_memory_size_a = 984 + 1312 + 456;
-       }
-       *num_part_y = lb_memory_size / memory_line_size_y;
-       *num_part_c = lb_memory_size_c / memory_line_size_c;
-       num_partitions_a = lb_memory_size_a / memory_line_size_a;
-
-       if (scl_data->lb_params.alpha_en
-                       && (num_partitions_a < *num_part_y))
-               *num_part_y = num_partitions_a;
-
-       if (*num_part_y > 64)
-               *num_part_y = 64;
-       if (*num_part_c > 64)
-               *num_part_c = 64;
-
-}
-
-static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps)
-{
-       if (ceil_vratio > 2)
-               return vtaps <= (num_partitions - ceil_vratio + 2);
-       else
-               return vtaps <= num_partitions;
-}
-
-/*find first match configuration which meets the min required lb size*/
-static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl_data)
-{
-       int num_part_y, num_part_c;
-       int vtaps = scl_data->taps.v_taps;
-       int vtaps_c = scl_data->taps.v_taps_c;
-       int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert);
-       int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c);
-
-       calc_lb_num_partitions(
-                       scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c);
-
-       if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
-                       && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
-               return LB_MEMORY_CONFIG_1;
-
-       calc_lb_num_partitions(
-                       scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c);
-
-       if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
-                       && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
-               return LB_MEMORY_CONFIG_2;
-
-       if (scl_data->format == PIXEL_FORMAT_420BPP8
-                       || scl_data->format == PIXEL_FORMAT_420BPP10) {
-               calc_lb_num_partitions(
-                               scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c);
-
-               if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
-                               && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
-                       return LB_MEMORY_CONFIG_3;
-       }
-
-       calc_lb_num_partitions(
-                       scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c);
-
-       /*Ensure we can support the requested number of vtaps*/
-       ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
-                       && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c));
-
-       return LB_MEMORY_CONFIG_0;
-}
-
-void dpp_set_scaler_auto_scale(
-       struct transform *xfm_base,
-       const struct scaler_data *scl_data)
-{
-       enum lb_memory_config lb_config;
-       struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
-       enum dscl_mode_sel dscl_mode = get_dscl_mode(
-                       scl_data, xfm_base->ctx->dc->debug.always_scale);
-       bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN
-                               && scl_data->format <= PIXEL_FORMAT_VIDEO_END;
-
-       dpp_set_overscan(xfm, scl_data);
-
-       dpp_set_otg_blank(xfm, scl_data);
-
-       REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode);
-
-       if (dscl_mode == DSCL_MODE_DSCL_BYPASS)
-               return;
-
-       lb_config =  find_lb_memory_config(scl_data);
-       dpp_set_lb(xfm, &scl_data->lb_params, lb_config);
-
-       if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS)
-               return;
-
-       /* TODO: v_min */
-       REG_SET_3(DSCL_AUTOCAL, 0,
-               AUTOCAL_MODE, AUTOCAL_MODE_AUTOSCALE,
-               AUTOCAL_NUM_PIPE, 0,
-               AUTOCAL_PIPE_ID, 0);
-
-       /* Black offsets */
-       if (ycbcr)
-               REG_SET_2(SCL_BLACK_OFFSET, 0,
-                               SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
-                               SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR);
-       else
-
-               REG_SET_2(SCL_BLACK_OFFSET, 0,
-                               SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
-                               SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y);
-
-       REG_SET_4(SCL_TAP_CONTROL, 0,
-               SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1,
-               SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1,
-               SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1,
-               SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1);
-
-       dpp_set_scl_filter(xfm, scl_data, ycbcr);
-}
-
 /* Program gamut remap in bypass mode */
 void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm)
 {
@@ -628,146 +120,6 @@ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm)
        /* Gamut remap in bypass */
 }
 
-static void dpp_set_recout(
-                       struct dcn10_dpp *xfm, const struct rect *recout)
-{
-       REG_SET_2(RECOUT_START, 0,
-               /* First pixel of RECOUT */
-                        RECOUT_START_X, recout->x,
-               /* First line of RECOUT */
-                        RECOUT_START_Y, recout->y);
-
-       REG_SET_2(RECOUT_SIZE, 0,
-               /* Number of RECOUT horizontal pixels */
-                        RECOUT_WIDTH, recout->width,
-               /* Number of RECOUT vertical lines */
-                        RECOUT_HEIGHT, recout->height
-                        - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 *
-                        (xfm->base.inst + 1));
-}
-
-static void dpp_set_manual_ratio_init(
-               struct dcn10_dpp *xfm, const struct scaler_data *data)
-{
-       uint32_t init_frac = 0;
-       uint32_t init_int = 0;
-
-       REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
-                       SCL_H_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.horz) << 5);
-
-       REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
-                       SCL_V_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.vert) << 5);
-
-       REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0,
-                       SCL_H_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.horz_c) << 5);
-
-       REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0,
-                       SCL_V_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.vert_c) << 5);
-
-       /*
-        * 0.24 format for fraction, first five bits zeroed
-        */
-       init_frac = dal_fixed31_32_u0d19(data->inits.h) << 5;
-       init_int = dal_fixed31_32_floor(data->inits.h);
-       REG_SET_2(SCL_HORZ_FILTER_INIT, 0,
-               SCL_H_INIT_FRAC, init_frac,
-               SCL_H_INIT_INT, init_int);
-
-       init_frac = dal_fixed31_32_u0d19(data->inits.h_c) << 5;
-       init_int = dal_fixed31_32_floor(data->inits.h_c);
-       REG_SET_2(SCL_HORZ_FILTER_INIT_C, 0,
-               SCL_H_INIT_FRAC_C, init_frac,
-               SCL_H_INIT_INT_C, init_int);
-
-       init_frac = dal_fixed31_32_u0d19(data->inits.v) << 5;
-       init_int = dal_fixed31_32_floor(data->inits.v);
-       REG_SET_2(SCL_VERT_FILTER_INIT, 0,
-               SCL_V_INIT_FRAC, init_frac,
-               SCL_V_INIT_INT, init_int);
-
-       init_frac = dal_fixed31_32_u0d19(data->inits.v_bot) << 5;
-       init_int = dal_fixed31_32_floor(data->inits.v_bot);
-       REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0,
-               SCL_V_INIT_FRAC_BOT, init_frac,
-               SCL_V_INIT_INT_BOT, init_int);
-
-       init_frac = dal_fixed31_32_u0d19(data->inits.v_c) << 5;
-       init_int = dal_fixed31_32_floor(data->inits.v_c);
-       REG_SET_2(SCL_VERT_FILTER_INIT_C, 0,
-               SCL_V_INIT_FRAC_C, init_frac,
-               SCL_V_INIT_INT_C, init_int);
-
-       init_frac = dal_fixed31_32_u0d19(data->inits.v_c_bot) << 5;
-       init_int = dal_fixed31_32_floor(data->inits.v_c_bot);
-       REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0,
-               SCL_V_INIT_FRAC_BOT_C, init_frac,
-               SCL_V_INIT_INT_BOT_C, init_int);
-}
-
-/* Main function to program scaler and line buffer in manual scaling mode */
-static void dpp_set_scaler_manual_scale(
-       struct transform *xfm_base,
-       const struct scaler_data *scl_data)
-{
-       enum lb_memory_config lb_config;
-       struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
-       enum dscl_mode_sel dscl_mode = get_dscl_mode(
-                       scl_data, xfm_base->ctx->dc->debug.always_scale);
-       bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN
-                               && scl_data->format <= PIXEL_FORMAT_VIDEO_END;
-
-       /* Recout */
-       dpp_set_recout(xfm, &scl_data->recout);
-
-       /* MPC Size */
-       REG_SET_2(MPC_SIZE, 0,
-               /* Number of horizontal pixels of MPC */
-                        MPC_WIDTH, scl_data->h_active,
-               /* Number of vertical lines of MPC */
-                        MPC_HEIGHT, scl_data->v_active);
-
-       /* SCL mode */
-       REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode);
-
-       if (dscl_mode == DSCL_MODE_DSCL_BYPASS)
-               return;
-       /* LB */
-       lb_config =  find_lb_memory_config(scl_data);
-       dpp_set_lb(xfm, &scl_data->lb_params, lb_config);
-
-       if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS)
-               return;
-
-       /* Autocal off */
-       REG_SET_3(DSCL_AUTOCAL, 0,
-               AUTOCAL_MODE, AUTOCAL_MODE_OFF,
-               AUTOCAL_NUM_PIPE, 0,
-               AUTOCAL_PIPE_ID, 0);
-
-       /* Black offsets */
-       if (ycbcr)
-               REG_SET_2(SCL_BLACK_OFFSET, 0,
-                               SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
-                               SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR);
-       else
-
-               REG_SET_2(SCL_BLACK_OFFSET, 0,
-                               SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
-                               SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y);
-
-       /* Manually calculate scale ratio and init values */
-       dpp_set_manual_ratio_init(xfm, scl_data);
-
-       /* HTaps/VTaps */
-       REG_SET_4(SCL_TAP_CONTROL, 0,
-               SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1,
-               SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1,
-               SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1,
-               SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1);
-
-       dpp_set_scl_filter(xfm, scl_data, ycbcr);
-}
-
 #define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19))
 
 
@@ -1561,7 +913,7 @@ static void oppn10_set_regamma_mode(
 
 static struct transform_funcs dcn10_dpp_funcs = {
                .transform_reset = dpp_reset,
-               .transform_set_scaler = dpp_set_scaler_manual_scale,
+               .transform_set_scaler = dcn10_dpp_set_scaler_manual_scale,
                .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps,
                .transform_set_gamut_remap = dcn_dpp_set_gamut_remap,
                .opp_set_csc_adjustment = oppn10_set_output_csc_adjustment,
index 1c9d332..496df1f 100644 (file)
@@ -1386,6 +1386,11 @@ struct dcn10_dpp {
        int lb_bits_per_entry;
        bool is_write_to_ram_a_safe;
 };
+
+void dcn10_dpp_set_scaler_manual_scale(
+       struct transform *xfm_base,
+       const struct scaler_data *scl_data);
+
 bool dcn10_dpp_construct(struct dcn10_dpp *xfm110,
        struct dc_context *ctx,
        uint32_t inst,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
new file mode 100644 (file)
index 0000000..95f014b
--- /dev/null
@@ -0,0 +1,762 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "core_types.h"
+
+#include "reg_helper.h"
+#include "dcn10_dpp.h"
+#include "basics/conversion.h"
+
+#define NUM_PHASES    64
+#define HORZ_MAX_TAPS 8
+#define VERT_MAX_TAPS 8
+
+#define BLACK_OFFSET_RGB_Y 0x0
+#define BLACK_OFFSET_CBCR  0x8000
+
+#define REG(reg)\
+       xfm->tf_regs->reg
+
+#define CTX \
+       xfm->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+       xfm->tf_shift->field_name, xfm->tf_mask->field_name
+
+enum dcn10_coef_filter_type_sel {
+       SCL_COEF_LUMA_VERT_FILTER = 0,
+       SCL_COEF_LUMA_HORZ_FILTER = 1,
+       SCL_COEF_CHROMA_VERT_FILTER = 2,
+       SCL_COEF_CHROMA_HORZ_FILTER = 3,
+       SCL_COEF_ALPHA_VERT_FILTER = 4,
+       SCL_COEF_ALPHA_HORZ_FILTER = 5
+};
+
+enum lb_memory_config {
+       /* Enable all 3 pieces of memory */
+       LB_MEMORY_CONFIG_0 = 0,
+
+       /* Enable only the first piece of memory */
+       LB_MEMORY_CONFIG_1 = 1,
+
+       /* Enable only the second piece of memory */
+       LB_MEMORY_CONFIG_2 = 2,
+
+       /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the
+        * last piece of chroma memory used for the luma storage
+        */
+       LB_MEMORY_CONFIG_3 = 3
+};
+
+enum dscl_autocal_mode {
+       AUTOCAL_MODE_OFF = 0,
+
+       /* Autocal calculate the scaling ratio and initial phase and the
+        * DSCL_MODE_SEL must be set to 1
+        */
+       AUTOCAL_MODE_AUTOSCALE = 1,
+       /* Autocal perform auto centering without replication and the
+        * DSCL_MODE_SEL must be set to 0
+        */
+       AUTOCAL_MODE_AUTOCENTER = 2,
+       /* Autocal perform auto centering and auto replication and the
+        * DSCL_MODE_SEL must be set to 0
+        */
+       AUTOCAL_MODE_AUTOREPLICATE = 3
+};
+
+enum dscl_mode_sel {
+       DSCL_MODE_SCALING_444_BYPASS = 0,
+       DSCL_MODE_SCALING_444_RGB_ENABLE = 1,
+       DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2,
+       DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3,
+       DSCL_MODE_SCALING_420_LUMA_BYPASS = 4,
+       DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5,
+       DSCL_MODE_DSCL_BYPASS = 6
+};
+
+enum gamut_remap_select {
+       GAMUT_REMAP_BYPASS = 0,
+       GAMUT_REMAP_COEFF,
+       GAMUT_REMAP_COMA_COEFF,
+       GAMUT_REMAP_COMB_COEFF
+};
+
+
+static void dpp_set_overscan(
+       struct dcn10_dpp *xfm,
+       const struct scaler_data *data)
+{
+       uint32_t left = data->recout.x;
+       uint32_t top = data->recout.y;
+
+       int right = data->h_active - data->recout.x - data->recout.width;
+       int bottom = data->v_active - data->recout.y - data->recout.height;
+
+       if (right < 0) {
+               BREAK_TO_DEBUGGER();
+               right = 0;
+       }
+       if (bottom < 0) {
+               BREAK_TO_DEBUGGER();
+               bottom = 0;
+       }
+
+       REG_SET_2(DSCL_EXT_OVERSCAN_LEFT_RIGHT, 0,
+               EXT_OVERSCAN_LEFT, left,
+               EXT_OVERSCAN_RIGHT, right);
+
+       REG_SET_2(DSCL_EXT_OVERSCAN_TOP_BOTTOM, 0,
+               EXT_OVERSCAN_BOTTOM, bottom,
+               EXT_OVERSCAN_TOP, top);
+}
+
+static void dpp_set_otg_blank(
+               struct dcn10_dpp *xfm, const struct scaler_data *data)
+{
+       uint32_t h_blank_start = data->h_active;
+       uint32_t h_blank_end = 0;
+       uint32_t v_blank_start = data->v_active;
+       uint32_t v_blank_end = 0;
+
+       REG_SET_2(OTG_H_BLANK, 0,
+                       OTG_H_BLANK_START, h_blank_start,
+                       OTG_H_BLANK_END, h_blank_end);
+
+       REG_SET_2(OTG_V_BLANK, 0,
+                       OTG_V_BLANK_START, v_blank_start,
+                       OTG_V_BLANK_END, v_blank_end);
+}
+
+static int get_pixel_depth_val(enum lb_pixel_depth depth)
+{
+       if (depth == LB_PIXEL_DEPTH_30BPP)
+               return 0; /* 10 bpc */
+       else if (depth == LB_PIXEL_DEPTH_24BPP)
+               return 1; /* 8 bpc */
+       else if (depth == LB_PIXEL_DEPTH_18BPP)
+               return 2; /* 6 bpc */
+       else if (depth == LB_PIXEL_DEPTH_36BPP)
+               return 3; /* 12 bpc */
+       else {
+               ASSERT(0);
+               return -1; /* Unsupported */
+       }
+}
+
+static enum dscl_mode_sel get_dscl_mode(
+               const struct scaler_data *data, bool dbg_always_scale)
+{
+       const long long one = dal_fixed31_32_one.value;
+       bool ycbcr = false;
+       bool format420 = false;
+
+       if (data->format == PIXEL_FORMAT_FP16)
+               return DSCL_MODE_DSCL_BYPASS;
+
+       if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN
+                       && data->format <= PIXEL_FORMAT_VIDEO_END)
+               ycbcr = true;
+
+       if (data->format == PIXEL_FORMAT_420BPP8 ||
+                       data->format == PIXEL_FORMAT_420BPP10)
+               format420 = true;
+
+       if (data->ratios.horz.value == one
+                       && data->ratios.vert.value == one
+                       && data->ratios.horz_c.value == one
+                       && data->ratios.vert_c.value == one
+                       && !dbg_always_scale)
+               return DSCL_MODE_SCALING_444_BYPASS;
+
+       if (!format420) {
+               if (ycbcr)
+                       return DSCL_MODE_SCALING_444_YCBCR_ENABLE;
+               else
+                       return DSCL_MODE_SCALING_444_RGB_ENABLE;
+       }
+       if (data->ratios.horz.value == one && data->ratios.vert.value == one)
+               return DSCL_MODE_SCALING_420_LUMA_BYPASS;
+       if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one)
+               return DSCL_MODE_SCALING_420_CHROMA_BYPASS;
+
+       return DSCL_MODE_SCALING_420_YCBCR_ENABLE;
+}
+
+static void dpp_set_lb(
+       struct dcn10_dpp *xfm,
+       const struct line_buffer_params *lb_params,
+       enum lb_memory_config mem_size_config)
+{
+       uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth);
+       uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth;
+       REG_SET_7(LB_DATA_FORMAT, 0,
+               PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */
+               PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */
+               PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */
+               DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */
+               DITHER_EN, 0, /* Dithering enable: Disabled */
+               INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */
+               ALPHA_EN, lb_params->alpha_en); /* Alpha enable */
+
+       REG_SET_2(LB_MEMORY_CTRL, 0,
+               MEMORY_CONFIG, mem_size_config,
+               LB_MAX_PARTITIONS, 63);
+}
+
+static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio)
+{
+       if (taps == 8)
+               return get_filter_8tap_64p(ratio);
+       else if (taps == 7)
+               return get_filter_7tap_64p(ratio);
+       else if (taps == 6)
+               return get_filter_6tap_64p(ratio);
+       else if (taps == 5)
+               return get_filter_5tap_64p(ratio);
+       else if (taps == 4)
+               return get_filter_4tap_64p(ratio);
+       else if (taps == 3)
+               return get_filter_3tap_64p(ratio);
+       else if (taps == 2)
+               return filter_2tap_64p;
+       else if (taps == 1)
+               return NULL;
+       else {
+               /* should never happen, bug */
+               BREAK_TO_DEBUGGER();
+               return NULL;
+       }
+}
+
+static void dpp_set_scaler_filter(
+               struct dcn10_dpp *xfm,
+               uint32_t taps,
+               enum dcn10_coef_filter_type_sel filter_type,
+               const uint16_t *filter)
+{
+       const int tap_pairs = (taps + 1) / 2;
+       int phase;
+       int pair;
+       uint16_t odd_coef, even_coef;
+
+       REG_SET_3(SCL_COEF_RAM_TAP_SELECT, 0,
+               SCL_COEF_RAM_TAP_PAIR_IDX, 0,
+               SCL_COEF_RAM_PHASE, 0,
+               SCL_COEF_RAM_FILTER_TYPE, filter_type);
+
+       for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) {
+               for (pair = 0; pair < tap_pairs; pair++) {
+                       even_coef = filter[phase * taps + 2 * pair];
+                       if ((pair * 2 + 1) < taps)
+                               odd_coef = filter[phase * taps + 2 * pair + 1];
+                       else
+                               odd_coef = 0;
+
+                       REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0,
+                               /* Even tap coefficient (bits 1:0 fixed to 0) */
+                               SCL_COEF_RAM_EVEN_TAP_COEF, even_coef,
+                               /* Write/read control for even coefficient */
+                               SCL_COEF_RAM_EVEN_TAP_COEF_EN, 1,
+                               /* Odd tap coefficient (bits 1:0 fixed to 0) */
+                               SCL_COEF_RAM_ODD_TAP_COEF, odd_coef,
+                               /* Write/read control for odd coefficient */
+                               SCL_COEF_RAM_ODD_TAP_COEF_EN, 1);
+               }
+       }
+
+}
+
+static void dpp_set_scl_filter(
+               struct dcn10_dpp *xfm,
+               const struct scaler_data *scl_data,
+               bool chroma_coef_mode)
+{
+       bool h_2tap_hardcode_coef_en = false;
+       bool v_2tap_hardcode_coef_en = false;
+       bool h_2tap_sharp_en = false;
+       bool v_2tap_sharp_en = false;
+       uint32_t h_2tap_sharp_factor = scl_data->sharpness.horz;
+       uint32_t v_2tap_sharp_factor = scl_data->sharpness.vert;
+       bool coef_ram_current;
+       const uint16_t *filter_h = NULL;
+       const uint16_t *filter_v = NULL;
+       const uint16_t *filter_h_c = NULL;
+       const uint16_t *filter_v_c = NULL;
+
+       h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3
+                                       && scl_data->taps.h_taps_c < 3
+               && (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1);
+       v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3
+                                       && scl_data->taps.v_taps_c < 3
+               && (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1);
+
+       h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0;
+       v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0;
+
+       REG_UPDATE_6(DSCL_2TAP_CONTROL,
+               SCL_H_2TAP_HARDCODE_COEF_EN, h_2tap_hardcode_coef_en,
+               SCL_H_2TAP_SHARP_EN, h_2tap_sharp_en,
+               SCL_H_2TAP_SHARP_FACTOR, h_2tap_sharp_factor,
+               SCL_V_2TAP_HARDCODE_COEF_EN, v_2tap_hardcode_coef_en,
+               SCL_V_2TAP_SHARP_EN, v_2tap_sharp_en,
+               SCL_V_2TAP_SHARP_FACTOR, v_2tap_sharp_factor);
+
+       if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) {
+               bool filter_updated = false;
+
+               filter_h = get_filter_coeffs_64p(
+                               scl_data->taps.h_taps, scl_data->ratios.horz);
+               filter_v = get_filter_coeffs_64p(
+                               scl_data->taps.v_taps, scl_data->ratios.vert);
+
+               filter_updated = (filter_h && (filter_h != xfm->filter_h))
+                               || (filter_v && (filter_v != xfm->filter_v));
+
+               if (chroma_coef_mode) {
+                       filter_h_c = get_filter_coeffs_64p(
+                                       scl_data->taps.h_taps_c, scl_data->ratios.horz_c);
+                       filter_v_c = get_filter_coeffs_64p(
+                                       scl_data->taps.v_taps_c, scl_data->ratios.vert_c);
+                       filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c))
+                                                       || (filter_v_c && (filter_v_c != xfm->filter_v_c));
+               }
+
+               if (filter_updated) {
+                       uint32_t scl_mode = REG_READ(SCL_MODE);
+
+                       if (!h_2tap_hardcode_coef_en && filter_h) {
+                               dpp_set_scaler_filter(
+                                       xfm, scl_data->taps.h_taps,
+                                       SCL_COEF_LUMA_HORZ_FILTER, filter_h);
+                       }
+                       xfm->filter_h = filter_h;
+                       if (!v_2tap_hardcode_coef_en && filter_v) {
+                               dpp_set_scaler_filter(
+                                       xfm, scl_data->taps.v_taps,
+                                       SCL_COEF_LUMA_VERT_FILTER, filter_v);
+                       }
+                       xfm->filter_v = filter_v;
+                       if (chroma_coef_mode) {
+                               if (!h_2tap_hardcode_coef_en && filter_h_c) {
+                                       dpp_set_scaler_filter(
+                                               xfm, scl_data->taps.h_taps_c,
+                                               SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c);
+                               }
+                               if (!v_2tap_hardcode_coef_en && filter_v_c) {
+                                       dpp_set_scaler_filter(
+                                               xfm, scl_data->taps.v_taps_c,
+                                               SCL_COEF_CHROMA_VERT_FILTER, filter_v_c);
+                               }
+                       }
+                       xfm->filter_h_c = filter_h_c;
+                       xfm->filter_v_c = filter_v_c;
+
+                       coef_ram_current = get_reg_field_value_ex(
+                               scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT,
+                               xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT);
+
+                       /* Swap coefficient RAM and set chroma coefficient mode */
+                       REG_SET_2(SCL_MODE, scl_mode,
+                                       SCL_COEF_RAM_SELECT, !coef_ram_current,
+                                       SCL_CHROMA_COEF_MODE, chroma_coef_mode);
+               }
+       }
+}
+
+static int get_lb_depth_bpc(enum lb_pixel_depth depth)
+{
+       if (depth == LB_PIXEL_DEPTH_30BPP)
+               return 10;
+       else if (depth == LB_PIXEL_DEPTH_24BPP)
+               return 8;
+       else if (depth == LB_PIXEL_DEPTH_18BPP)
+               return 6;
+       else if (depth == LB_PIXEL_DEPTH_36BPP)
+               return 12;
+       else {
+               BREAK_TO_DEBUGGER();
+               return -1; /* Unsupported */
+       }
+}
+
+static void calc_lb_num_partitions(
+               const struct scaler_data *scl_data,
+               enum lb_memory_config lb_config,
+               int *num_part_y,
+               int *num_part_c)
+{
+       int line_size = scl_data->viewport.width < scl_data->recout.width ?
+                       scl_data->viewport.width : scl_data->recout.width;
+       int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ?
+                       scl_data->viewport_c.width : scl_data->recout.width;
+       int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth);
+       int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */
+       int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */
+       int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */
+       int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a;
+
+       if (lb_config == LB_MEMORY_CONFIG_1) {
+               lb_memory_size = 816;
+               lb_memory_size_c = 816;
+               lb_memory_size_a = 984;
+       } else if (lb_config == LB_MEMORY_CONFIG_2) {
+               lb_memory_size = 1088;
+               lb_memory_size_c = 1088;
+               lb_memory_size_a = 1312;
+       } else if (lb_config == LB_MEMORY_CONFIG_3) {
+               lb_memory_size = 816 + 1088 + 848 + 848 + 848;
+               lb_memory_size_c = 816 + 1088;
+               lb_memory_size_a = 984 + 1312 + 456;
+       } else {
+               lb_memory_size = 816 + 1088 + 848;
+               lb_memory_size_c = 816 + 1088 + 848;
+               lb_memory_size_a = 984 + 1312 + 456;
+       }
+       *num_part_y = lb_memory_size / memory_line_size_y;
+       *num_part_c = lb_memory_size_c / memory_line_size_c;
+       num_partitions_a = lb_memory_size_a / memory_line_size_a;
+
+       if (scl_data->lb_params.alpha_en
+                       && (num_partitions_a < *num_part_y))
+               *num_part_y = num_partitions_a;
+
+       if (*num_part_y > 64)
+               *num_part_y = 64;
+       if (*num_part_c > 64)
+               *num_part_c = 64;
+
+}
+
+static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps)
+{
+       if (ceil_vratio > 2)
+               return vtaps <= (num_partitions - ceil_vratio + 2);
+       else
+               return vtaps <= num_partitions;
+}
+
+/*find first match configuration which meets the min required lb size*/
+static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl_data)
+{
+       int num_part_y, num_part_c;
+       int vtaps = scl_data->taps.v_taps;
+       int vtaps_c = scl_data->taps.v_taps_c;
+       int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert);
+       int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c);
+
+       calc_lb_num_partitions(
+                       scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c);
+
+       if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
+                       && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
+               return LB_MEMORY_CONFIG_1;
+
+       calc_lb_num_partitions(
+                       scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c);
+
+       if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
+                       && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
+               return LB_MEMORY_CONFIG_2;
+
+       if (scl_data->format == PIXEL_FORMAT_420BPP8
+                       || scl_data->format == PIXEL_FORMAT_420BPP10) {
+               calc_lb_num_partitions(
+                               scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c);
+
+               if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
+                               && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
+                       return LB_MEMORY_CONFIG_3;
+       }
+
+       calc_lb_num_partitions(
+                       scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c);
+
+       /*Ensure we can support the requested number of vtaps*/
+       ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
+                       && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c));
+
+       return LB_MEMORY_CONFIG_0;
+}
+
+void dpp_set_scaler_auto_scale(
+       struct transform *xfm_base,
+       const struct scaler_data *scl_data)
+{
+       enum lb_memory_config lb_config;
+       struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
+       enum dscl_mode_sel dscl_mode = get_dscl_mode(
+                       scl_data, xfm_base->ctx->dc->debug.always_scale);
+       bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN
+                               && scl_data->format <= PIXEL_FORMAT_VIDEO_END;
+
+       dpp_set_overscan(xfm, scl_data);
+
+       dpp_set_otg_blank(xfm, scl_data);
+
+       REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode);
+
+       if (dscl_mode == DSCL_MODE_DSCL_BYPASS)
+               return;
+
+       lb_config =  find_lb_memory_config(scl_data);
+       dpp_set_lb(xfm, &scl_data->lb_params, lb_config);
+
+       if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS)
+               return;
+
+       /* TODO: v_min */
+       REG_SET_3(DSCL_AUTOCAL, 0,
+               AUTOCAL_MODE, AUTOCAL_MODE_AUTOSCALE,
+               AUTOCAL_NUM_PIPE, 0,
+               AUTOCAL_PIPE_ID, 0);
+
+       /* Black offsets */
+       if (ycbcr)
+               REG_SET_2(SCL_BLACK_OFFSET, 0,
+                               SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
+                               SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR);
+       else
+
+               REG_SET_2(SCL_BLACK_OFFSET, 0,
+                               SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
+                               SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y);
+
+       REG_SET_4(SCL_TAP_CONTROL, 0,
+               SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1,
+               SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1,
+               SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1,
+               SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1);
+
+       dpp_set_scl_filter(xfm, scl_data, ycbcr);
+}
+
+
+static void dpp_set_manual_ratio_init(
+               struct dcn10_dpp *xfm, const struct scaler_data *data)
+{
+       uint32_t init_frac = 0;
+       uint32_t init_int = 0;
+
+       REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
+                       SCL_H_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.horz) << 5);
+
+       REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
+                       SCL_V_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.vert) << 5);
+
+       REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0,
+                       SCL_H_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.horz_c) << 5);
+
+       REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0,
+                       SCL_V_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.vert_c) << 5);
+
+       /*
+        * 0.24 format for fraction, first five bits zeroed
+        */
+       init_frac = dal_fixed31_32_u0d19(data->inits.h) << 5;
+       init_int = dal_fixed31_32_floor(data->inits.h);
+       REG_SET_2(SCL_HORZ_FILTER_INIT, 0,
+               SCL_H_INIT_FRAC, init_frac,
+               SCL_H_INIT_INT, init_int);
+
+       init_frac = dal_fixed31_32_u0d19(data->inits.h_c) << 5;
+       init_int = dal_fixed31_32_floor(data->inits.h_c);
+       REG_SET_2(SCL_HORZ_FILTER_INIT_C, 0,
+               SCL_H_INIT_FRAC_C, init_frac,
+               SCL_H_INIT_INT_C, init_int);
+
+       init_frac = dal_fixed31_32_u0d19(data->inits.v) << 5;
+       init_int = dal_fixed31_32_floor(data->inits.v);
+       REG_SET_2(SCL_VERT_FILTER_INIT, 0,
+               SCL_V_INIT_FRAC, init_frac,
+               SCL_V_INIT_INT, init_int);
+
+       init_frac = dal_fixed31_32_u0d19(data->inits.v_bot) << 5;
+       init_int = dal_fixed31_32_floor(data->inits.v_bot);
+       REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0,
+               SCL_V_INIT_FRAC_BOT, init_frac,
+               SCL_V_INIT_INT_BOT, init_int);
+
+       init_frac = dal_fixed31_32_u0d19(data->inits.v_c) << 5;
+       init_int = dal_fixed31_32_floor(data->inits.v_c);
+       REG_SET_2(SCL_VERT_FILTER_INIT_C, 0,
+               SCL_V_INIT_FRAC_C, init_frac,
+               SCL_V_INIT_INT_C, init_int);
+
+       init_frac = dal_fixed31_32_u0d19(data->inits.v_c_bot) << 5;
+       init_int = dal_fixed31_32_floor(data->inits.v_c_bot);
+       REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0,
+               SCL_V_INIT_FRAC_BOT_C, init_frac,
+               SCL_V_INIT_INT_BOT_C, init_int);
+}
+
+
+
+static void dpp_set_recout(
+                       struct dcn10_dpp *xfm, const struct rect *recout)
+{
+       REG_SET_2(RECOUT_START, 0,
+               /* First pixel of RECOUT */
+                        RECOUT_START_X, recout->x,
+               /* First line of RECOUT */
+                        RECOUT_START_Y, recout->y);
+
+       REG_SET_2(RECOUT_SIZE, 0,
+               /* Number of RECOUT horizontal pixels */
+                        RECOUT_WIDTH, recout->width,
+               /* Number of RECOUT vertical lines */
+                        RECOUT_HEIGHT, recout->height
+                        - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 *
+                        (xfm->base.inst + 1));
+}
+
+/* Main function to program scaler and line buffer in manual scaling mode */
+void dcn10_dpp_set_scaler_manual_scale(
+       struct transform *xfm_base,
+       const struct scaler_data *scl_data)
+{
+       enum lb_memory_config lb_config;
+       struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
+       enum dscl_mode_sel dscl_mode = get_dscl_mode(
+                       scl_data, xfm_base->ctx->dc->debug.always_scale);
+       bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN
+                               && scl_data->format <= PIXEL_FORMAT_VIDEO_END;
+
+       /* Recout */
+       dpp_set_recout(xfm, &scl_data->recout);
+
+       /* MPC Size */
+       REG_SET_2(MPC_SIZE, 0,
+               /* Number of horizontal pixels of MPC */
+                        MPC_WIDTH, scl_data->h_active,
+               /* Number of vertical lines of MPC */
+                        MPC_HEIGHT, scl_data->v_active);
+
+       /* SCL mode */
+       REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode);
+
+       if (dscl_mode == DSCL_MODE_DSCL_BYPASS)
+               return;
+       /* LB */
+       lb_config =  find_lb_memory_config(scl_data);
+       dpp_set_lb(xfm, &scl_data->lb_params, lb_config);
+
+       if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS)
+               return;
+
+       /* Autocal off */
+       REG_SET_3(DSCL_AUTOCAL, 0,
+               AUTOCAL_MODE, AUTOCAL_MODE_OFF,
+               AUTOCAL_NUM_PIPE, 0,
+               AUTOCAL_PIPE_ID, 0);
+
+       /* Black offsets */
+       if (ycbcr)
+               REG_SET_2(SCL_BLACK_OFFSET, 0,
+                               SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
+                               SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR);
+       else
+
+               REG_SET_2(SCL_BLACK_OFFSET, 0,
+                               SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
+                               SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y);
+
+       /* Manually calculate scale ratio and init values */
+       dpp_set_manual_ratio_init(xfm, scl_data);
+
+       /* HTaps/VTaps */
+       REG_SET_4(SCL_TAP_CONTROL, 0,
+               SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1,
+               SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1,
+               SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1,
+               SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1);
+
+       dpp_set_scl_filter(xfm, scl_data, ycbcr);
+}
+
+
+#if 0
+bool dpp_set_pixel_storage_depth(
+       struct dpp *xfm,
+       enum lb_pixel_depth depth,
+       const struct bit_depth_reduction_params *bit_depth_params)
+{
+       struct dcn10_dpp *xfm110 = TO_DCN10_DPP(xfm);
+       bool ret = true;
+       uint32_t value;
+       enum dc_color_depth color_depth;
+
+       value = dm_read_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT));
+       switch (depth) {
+       case LB_PIXEL_DEPTH_18BPP:
+               color_depth = COLOR_DEPTH_666;
+               set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH);
+               set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+               break;
+       case LB_PIXEL_DEPTH_24BPP:
+               color_depth = COLOR_DEPTH_888;
+               set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH);
+               set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+               break;
+       case LB_PIXEL_DEPTH_30BPP:
+               color_depth = COLOR_DEPTH_101010;
+               set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH);
+               set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+               break;
+       case LB_PIXEL_DEPTH_36BPP:
+               color_depth = COLOR_DEPTH_121212;
+               set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH);
+               set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+               break;
+       default:
+               ret = false;
+               break;
+       }
+
+       if (ret == true) {
+               set_denormalization(xfm110, color_depth);
+               ret = program_bit_depth_reduction(xfm110, color_depth,
+                               bit_depth_params);
+
+               set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN);
+               dm_write_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value);
+               if (!(xfm110->lb_pixel_depth_supported & depth)) {
+                       /* We should use unsupported capabilities
+                        * unless it is required by w/a
+                        */
+                       dm_logger_write(xfm->ctx->logger, LOG_WARNING,
+                               "%s: Capability not supported",
+                               __func__);
+               }
+       }
+
+       return ret;
+}
+#endif
+
+