Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-16 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #include "dce_transform.h"
0027 #include "reg_helper.h"
0028 #include "opp.h"
0029 #include "basics/conversion.h"
0030 #include "dc.h"
0031 
0032 #define REG(reg) \
0033     (xfm_dce->regs->reg)
0034 
0035 #undef FN
0036 #define FN(reg_name, field_name) \
0037     xfm_dce->xfm_shift->field_name, xfm_dce->xfm_mask->field_name
0038 
0039 #define CTX \
0040     xfm_dce->base.ctx
0041 #define DC_LOGGER \
0042     xfm_dce->base.ctx->logger
0043 
0044 #define IDENTITY_RATIO(ratio) (dc_fixpt_u2d19(ratio) == (1 << 19))
0045 #define GAMUT_MATRIX_SIZE 12
0046 #define SCL_PHASES 16
0047 
0048 enum dcp_out_trunc_round_mode {
0049     DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
0050     DCP_OUT_TRUNC_ROUND_MODE_ROUND
0051 };
0052 
0053 enum dcp_out_trunc_round_depth {
0054     DCP_OUT_TRUNC_ROUND_DEPTH_14BIT,
0055     DCP_OUT_TRUNC_ROUND_DEPTH_13BIT,
0056     DCP_OUT_TRUNC_ROUND_DEPTH_12BIT,
0057     DCP_OUT_TRUNC_ROUND_DEPTH_11BIT,
0058     DCP_OUT_TRUNC_ROUND_DEPTH_10BIT,
0059     DCP_OUT_TRUNC_ROUND_DEPTH_9BIT,
0060     DCP_OUT_TRUNC_ROUND_DEPTH_8BIT
0061 };
0062 
0063 /*  defines the various methods of bit reduction available for use */
0064 enum dcp_bit_depth_reduction_mode {
0065     DCP_BIT_DEPTH_REDUCTION_MODE_DITHER,
0066     DCP_BIT_DEPTH_REDUCTION_MODE_ROUND,
0067     DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE,
0068     DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED,
0069     DCP_BIT_DEPTH_REDUCTION_MODE_INVALID
0070 };
0071 
0072 enum dcp_spatial_dither_mode {
0073     DCP_SPATIAL_DITHER_MODE_AAAA,
0074     DCP_SPATIAL_DITHER_MODE_A_AA_A,
0075     DCP_SPATIAL_DITHER_MODE_AABBAABB,
0076     DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC,
0077     DCP_SPATIAL_DITHER_MODE_INVALID
0078 };
0079 
0080 enum dcp_spatial_dither_depth {
0081     DCP_SPATIAL_DITHER_DEPTH_30BPP,
0082     DCP_SPATIAL_DITHER_DEPTH_24BPP
0083 };
0084 
0085 enum csc_color_mode {
0086     /* 00 - BITS2:0 Bypass */
0087     CSC_COLOR_MODE_GRAPHICS_BYPASS,
0088     /* 01 - hard coded coefficient TV RGB */
0089     CSC_COLOR_MODE_GRAPHICS_PREDEFINED,
0090     /* 04 - programmable OUTPUT CSC coefficient */
0091     CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC,
0092 };
0093 
0094 enum grph_color_adjust_option {
0095     GRPH_COLOR_MATRIX_HW_DEFAULT = 1,
0096     GRPH_COLOR_MATRIX_SW
0097 };
0098 
0099 static const struct out_csc_color_matrix global_color_matrix[] = {
0100 { COLOR_SPACE_SRGB,
0101     { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
0102 { COLOR_SPACE_SRGB_LIMITED,
0103     { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} },
0104 { COLOR_SPACE_YCBCR601,
0105     { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47,
0106         0xF6B9, 0xE00, 0x1000} },
0107 { COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA,
0108     0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
0109 /* TODO: correct values below */
0110 { COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
0111     0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
0112 { COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
0113     0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
0114 };
0115 
0116 static bool setup_scaling_configuration(
0117     struct dce_transform *xfm_dce,
0118     const struct scaler_data *data)
0119 {
0120     REG_SET(SCL_BYPASS_CONTROL, 0, SCL_BYPASS_MODE, 0);
0121 
0122     if (data->taps.h_taps + data->taps.v_taps <= 2) {
0123         /* Set bypass */
0124         if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0)
0125             REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0);
0126         else
0127             REG_UPDATE(SCL_MODE, SCL_MODE, 0);
0128         return false;
0129     }
0130 
0131     REG_SET_2(SCL_TAP_CONTROL, 0,
0132             SCL_H_NUM_OF_TAPS, data->taps.h_taps - 1,
0133             SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1);
0134 
0135     if (data->format <= PIXEL_FORMAT_GRPH_END)
0136         REG_UPDATE(SCL_MODE, SCL_MODE, 1);
0137     else
0138         REG_UPDATE(SCL_MODE, SCL_MODE, 2);
0139 
0140     if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0)
0141         REG_UPDATE(SCL_MODE, SCL_PSCL_EN, 1);
0142 
0143     /* 1 - Replace out of bound pixels with edge */
0144     REG_SET(SCL_CONTROL, 0, SCL_BOUNDARY_MODE, 1);
0145 
0146     return true;
0147 }
0148 
0149 #if defined(CONFIG_DRM_AMD_DC_SI)
0150 static bool dce60_setup_scaling_configuration(
0151     struct dce_transform *xfm_dce,
0152     const struct scaler_data *data)
0153 {
0154     REG_SET(SCL_BYPASS_CONTROL, 0, SCL_BYPASS_MODE, 0);
0155 
0156     if (data->taps.h_taps + data->taps.v_taps <= 2) {
0157         /* Set bypass */
0158 
0159         /* DCE6 has no SCL_MODE register, skip scale mode programming */
0160 
0161         return false;
0162     }
0163 
0164     REG_SET_2(SCL_TAP_CONTROL, 0,
0165             SCL_H_NUM_OF_TAPS, data->taps.h_taps - 1,
0166             SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1);
0167 
0168     /* DCE6 has no SCL_MODE register, skip scale mode programming */
0169 
0170     /* DCE6 has no SCL_BOUNDARY_MODE bit, skip replace out of bound pixels */
0171 
0172     return true;
0173 }
0174 #endif
0175 
0176 static void program_overscan(
0177         struct dce_transform *xfm_dce,
0178         const struct scaler_data *data)
0179 {
0180     int overscan_right = data->h_active
0181             - data->recout.x - data->recout.width;
0182     int overscan_bottom = data->v_active
0183             - data->recout.y - data->recout.height;
0184 
0185     if (xfm_dce->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) {
0186         overscan_bottom += 2;
0187         overscan_right += 2;
0188     }
0189 
0190     if (overscan_right < 0) {
0191         BREAK_TO_DEBUGGER();
0192         overscan_right = 0;
0193     }
0194     if (overscan_bottom < 0) {
0195         BREAK_TO_DEBUGGER();
0196         overscan_bottom = 0;
0197     }
0198 
0199     REG_SET_2(EXT_OVERSCAN_LEFT_RIGHT, 0,
0200             EXT_OVERSCAN_LEFT, data->recout.x,
0201             EXT_OVERSCAN_RIGHT, overscan_right);
0202     REG_SET_2(EXT_OVERSCAN_TOP_BOTTOM, 0,
0203             EXT_OVERSCAN_TOP, data->recout.y,
0204             EXT_OVERSCAN_BOTTOM, overscan_bottom);
0205 }
0206 
0207 static void program_multi_taps_filter(
0208     struct dce_transform *xfm_dce,
0209     int taps,
0210     const uint16_t *coeffs,
0211     enum ram_filter_type filter_type)
0212 {
0213     int phase, pair;
0214     int array_idx = 0;
0215     int taps_pairs = (taps + 1) / 2;
0216     int phases_to_program = SCL_PHASES / 2 + 1;
0217 
0218     uint32_t power_ctl = 0;
0219 
0220     if (!coeffs)
0221         return;
0222 
0223     /*We need to disable power gating on coeff memory to do programming*/
0224     if (REG(DCFE_MEM_PWR_CTRL)) {
0225         power_ctl = REG_READ(DCFE_MEM_PWR_CTRL);
0226         REG_SET(DCFE_MEM_PWR_CTRL, power_ctl, SCL_COEFF_MEM_PWR_DIS, 1);
0227 
0228         REG_WAIT(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, 0, 1, 10);
0229     }
0230     for (phase = 0; phase < phases_to_program; phase++) {
0231         /*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror
0232         phase 0 is unique and phase N/2 is unique if N is even*/
0233         for (pair = 0; pair < taps_pairs; pair++) {
0234             uint16_t odd_coeff = 0;
0235             uint16_t even_coeff = coeffs[array_idx];
0236 
0237             REG_SET_3(SCL_COEF_RAM_SELECT, 0,
0238                     SCL_C_RAM_FILTER_TYPE, filter_type,
0239                     SCL_C_RAM_PHASE, phase,
0240                     SCL_C_RAM_TAP_PAIR_IDX, pair);
0241 
0242             if (taps % 2 && pair == taps_pairs - 1)
0243                 array_idx++;
0244             else {
0245                 odd_coeff = coeffs[array_idx + 1];
0246                 array_idx += 2;
0247             }
0248 
0249             REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0,
0250                     SCL_C_RAM_EVEN_TAP_COEF_EN, 1,
0251                     SCL_C_RAM_EVEN_TAP_COEF, even_coeff,
0252                     SCL_C_RAM_ODD_TAP_COEF_EN, 1,
0253                     SCL_C_RAM_ODD_TAP_COEF, odd_coeff);
0254         }
0255     }
0256 
0257     /*We need to restore power gating on coeff memory to initial state*/
0258     if (REG(DCFE_MEM_PWR_CTRL))
0259         REG_WRITE(DCFE_MEM_PWR_CTRL, power_ctl);
0260 }
0261 
0262 static void program_viewport(
0263     struct dce_transform *xfm_dce,
0264     const struct rect *view_port)
0265 {
0266     REG_SET_2(VIEWPORT_START, 0,
0267             VIEWPORT_X_START, view_port->x,
0268             VIEWPORT_Y_START, view_port->y);
0269 
0270     REG_SET_2(VIEWPORT_SIZE, 0,
0271             VIEWPORT_HEIGHT, view_port->height,
0272             VIEWPORT_WIDTH, view_port->width);
0273 
0274     /* TODO: add stereo support */
0275 }
0276 
0277 static void calculate_inits(
0278     struct dce_transform *xfm_dce,
0279     const struct scaler_data *data,
0280     struct scl_ratios_inits *inits)
0281 {
0282     struct fixed31_32 h_init;
0283     struct fixed31_32 v_init;
0284 
0285     inits->h_int_scale_ratio =
0286         dc_fixpt_u2d19(data->ratios.horz) << 5;
0287     inits->v_int_scale_ratio =
0288         dc_fixpt_u2d19(data->ratios.vert) << 5;
0289 
0290     h_init =
0291         dc_fixpt_div_int(
0292             dc_fixpt_add(
0293                 data->ratios.horz,
0294                 dc_fixpt_from_int(data->taps.h_taps + 1)),
0295                 2);
0296     inits->h_init.integer = dc_fixpt_floor(h_init);
0297     inits->h_init.fraction = dc_fixpt_u0d19(h_init) << 5;
0298 
0299     v_init =
0300         dc_fixpt_div_int(
0301             dc_fixpt_add(
0302                 data->ratios.vert,
0303                 dc_fixpt_from_int(data->taps.v_taps + 1)),
0304                 2);
0305     inits->v_init.integer = dc_fixpt_floor(v_init);
0306     inits->v_init.fraction = dc_fixpt_u0d19(v_init) << 5;
0307 }
0308 
0309 #if defined(CONFIG_DRM_AMD_DC_SI)
0310 static void dce60_calculate_inits(
0311     struct dce_transform *xfm_dce,
0312     const struct scaler_data *data,
0313     struct sclh_ratios_inits *inits)
0314 {
0315     struct fixed31_32 v_init;
0316 
0317     inits->h_int_scale_ratio =
0318         dc_fixpt_u2d19(data->ratios.horz) << 5;
0319     inits->v_int_scale_ratio =
0320         dc_fixpt_u2d19(data->ratios.vert) << 5;
0321 
0322     /* DCE6 h_init_luma setting inspired by DCE110 */
0323     inits->h_init_luma.integer = 1;
0324 
0325     /* DCE6 h_init_chroma setting inspired by DCE110 */
0326     inits->h_init_chroma.integer = 1;
0327 
0328     v_init =
0329         dc_fixpt_div_int(
0330             dc_fixpt_add(
0331                 data->ratios.vert,
0332                 dc_fixpt_from_int(data->taps.v_taps + 1)),
0333                 2);
0334     inits->v_init.integer = dc_fixpt_floor(v_init);
0335     inits->v_init.fraction = dc_fixpt_u0d19(v_init) << 5;
0336 }
0337 #endif
0338 
0339 static void program_scl_ratios_inits(
0340     struct dce_transform *xfm_dce,
0341     struct scl_ratios_inits *inits)
0342 {
0343 
0344     REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
0345             SCL_H_SCALE_RATIO, inits->h_int_scale_ratio);
0346 
0347     REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
0348             SCL_V_SCALE_RATIO, inits->v_int_scale_ratio);
0349 
0350     REG_SET_2(SCL_HORZ_FILTER_INIT, 0,
0351             SCL_H_INIT_INT, inits->h_init.integer,
0352             SCL_H_INIT_FRAC, inits->h_init.fraction);
0353 
0354     REG_SET_2(SCL_VERT_FILTER_INIT, 0,
0355             SCL_V_INIT_INT, inits->v_init.integer,
0356             SCL_V_INIT_FRAC, inits->v_init.fraction);
0357 
0358     REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0);
0359 }
0360 
0361 #if defined(CONFIG_DRM_AMD_DC_SI)
0362 static void dce60_program_scl_ratios_inits(
0363     struct dce_transform *xfm_dce,
0364     struct sclh_ratios_inits *inits)
0365 {
0366 
0367     REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
0368             SCL_H_SCALE_RATIO, inits->h_int_scale_ratio);
0369 
0370     REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
0371             SCL_V_SCALE_RATIO, inits->v_int_scale_ratio);
0372 
0373     /* DCE6 has SCL_HORZ_FILTER_INIT_RGB_LUMA register */
0374     REG_SET_2(SCL_HORZ_FILTER_INIT_RGB_LUMA, 0,
0375             SCL_H_INIT_INT_RGB_Y, inits->h_init_luma.integer,
0376             SCL_H_INIT_FRAC_RGB_Y, inits->h_init_luma.fraction);
0377 
0378     /* DCE6 has SCL_HORZ_FILTER_INIT_CHROMA register */
0379     REG_SET_2(SCL_HORZ_FILTER_INIT_CHROMA, 0,
0380             SCL_H_INIT_INT_CBCR, inits->h_init_chroma.integer,
0381             SCL_H_INIT_FRAC_CBCR, inits->h_init_chroma.fraction);
0382 
0383     REG_SET_2(SCL_VERT_FILTER_INIT, 0,
0384             SCL_V_INIT_INT, inits->v_init.integer,
0385             SCL_V_INIT_FRAC, inits->v_init.fraction);
0386 
0387     REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0);
0388 }
0389 #endif
0390 
0391 static const uint16_t *get_filter_coeffs_16p(int taps, struct fixed31_32 ratio)
0392 {
0393     if (taps == 4)
0394         return get_filter_4tap_16p(ratio);
0395     else if (taps == 3)
0396         return get_filter_3tap_16p(ratio);
0397     else if (taps == 2)
0398         return get_filter_2tap_16p();
0399     else if (taps == 1)
0400         return NULL;
0401     else {
0402         /* should never happen, bug */
0403         BREAK_TO_DEBUGGER();
0404         return NULL;
0405     }
0406 }
0407 
0408 static void dce_transform_set_scaler(
0409     struct transform *xfm,
0410     const struct scaler_data *data)
0411 {
0412     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
0413     bool is_scaling_required;
0414     bool filter_updated = false;
0415     const uint16_t *coeffs_v, *coeffs_h;
0416 
0417     /*Use all three pieces of memory always*/
0418     REG_SET_2(LB_MEMORY_CTRL, 0,
0419             LB_MEMORY_CONFIG, 0,
0420             LB_MEMORY_SIZE, xfm_dce->lb_memory_size);
0421 
0422     /* Clear SCL_F_SHARP_CONTROL value to 0 */
0423     REG_WRITE(SCL_F_SHARP_CONTROL, 0);
0424 
0425     /* 1. Program overscan */
0426     program_overscan(xfm_dce, data);
0427 
0428     /* 2. Program taps and configuration */
0429     is_scaling_required = setup_scaling_configuration(xfm_dce, data);
0430 
0431     if (is_scaling_required) {
0432         /* 3. Calculate and program ratio, filter initialization */
0433         struct scl_ratios_inits inits = { 0 };
0434 
0435         calculate_inits(xfm_dce, data, &inits);
0436 
0437         program_scl_ratios_inits(xfm_dce, &inits);
0438 
0439         coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert);
0440         coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz);
0441 
0442         if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) {
0443             /* 4. Program vertical filters */
0444             if (xfm_dce->filter_v == NULL)
0445                 REG_SET(SCL_VERT_FILTER_CONTROL, 0,
0446                         SCL_V_2TAP_HARDCODE_COEF_EN, 0);
0447             program_multi_taps_filter(
0448                     xfm_dce,
0449                     data->taps.v_taps,
0450                     coeffs_v,
0451                     FILTER_TYPE_RGB_Y_VERTICAL);
0452             program_multi_taps_filter(
0453                     xfm_dce,
0454                     data->taps.v_taps,
0455                     coeffs_v,
0456                     FILTER_TYPE_ALPHA_VERTICAL);
0457 
0458             /* 5. Program horizontal filters */
0459             if (xfm_dce->filter_h == NULL)
0460                 REG_SET(SCL_HORZ_FILTER_CONTROL, 0,
0461                         SCL_H_2TAP_HARDCODE_COEF_EN, 0);
0462             program_multi_taps_filter(
0463                     xfm_dce,
0464                     data->taps.h_taps,
0465                     coeffs_h,
0466                     FILTER_TYPE_RGB_Y_HORIZONTAL);
0467             program_multi_taps_filter(
0468                     xfm_dce,
0469                     data->taps.h_taps,
0470                     coeffs_h,
0471                     FILTER_TYPE_ALPHA_HORIZONTAL);
0472 
0473             xfm_dce->filter_v = coeffs_v;
0474             xfm_dce->filter_h = coeffs_h;
0475             filter_updated = true;
0476         }
0477     }
0478 
0479     /* 6. Program the viewport */
0480     program_viewport(xfm_dce, &data->viewport);
0481 
0482     /* 7. Set bit to flip to new coefficient memory */
0483     if (filter_updated)
0484         REG_UPDATE(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, 1);
0485 
0486     REG_UPDATE(LB_DATA_FORMAT, ALPHA_EN, data->lb_params.alpha_en);
0487 }
0488 
0489 #if defined(CONFIG_DRM_AMD_DC_SI)
0490 static void dce60_transform_set_scaler(
0491     struct transform *xfm,
0492     const struct scaler_data *data)
0493 {
0494     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
0495     bool is_scaling_required;
0496     const uint16_t *coeffs_v, *coeffs_h;
0497 
0498     /*Use whole line buffer memory always*/
0499     REG_SET(DC_LB_MEMORY_SPLIT, 0,
0500         DC_LB_MEMORY_CONFIG, 0);
0501 
0502     REG_SET(DC_LB_MEM_SIZE, 0,
0503         DC_LB_MEM_SIZE, xfm_dce->lb_memory_size);
0504 
0505     /* Clear SCL_F_SHARP_CONTROL value to 0 */
0506     REG_WRITE(SCL_F_SHARP_CONTROL, 0);
0507 
0508     /* 1. Program overscan */
0509     program_overscan(xfm_dce, data);
0510 
0511     /* 2. Program taps and configuration */
0512     is_scaling_required = dce60_setup_scaling_configuration(xfm_dce, data);
0513 
0514     if (is_scaling_required) {
0515         /* 3. Calculate and program ratio, DCE6 filter initialization */
0516         struct sclh_ratios_inits inits = { 0 };
0517 
0518         /* DCE6 has specific calculate_inits() function */
0519         dce60_calculate_inits(xfm_dce, data, &inits);
0520 
0521         /* DCE6 has specific program_scl_ratios_inits() function */
0522         dce60_program_scl_ratios_inits(xfm_dce, &inits);
0523 
0524         coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert);
0525         coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz);
0526 
0527         if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) {
0528             /* 4. Program vertical filters */
0529             if (xfm_dce->filter_v == NULL)
0530                 REG_SET(SCL_VERT_FILTER_CONTROL, 0,
0531                         SCL_V_2TAP_HARDCODE_COEF_EN, 0);
0532             program_multi_taps_filter(
0533                     xfm_dce,
0534                     data->taps.v_taps,
0535                     coeffs_v,
0536                     FILTER_TYPE_RGB_Y_VERTICAL);
0537             program_multi_taps_filter(
0538                     xfm_dce,
0539                     data->taps.v_taps,
0540                     coeffs_v,
0541                     FILTER_TYPE_ALPHA_VERTICAL);
0542 
0543             /* 5. Program horizontal filters */
0544             if (xfm_dce->filter_h == NULL)
0545                 REG_SET(SCL_HORZ_FILTER_CONTROL, 0,
0546                         SCL_H_2TAP_HARDCODE_COEF_EN, 0);
0547             program_multi_taps_filter(
0548                     xfm_dce,
0549                     data->taps.h_taps,
0550                     coeffs_h,
0551                     FILTER_TYPE_RGB_Y_HORIZONTAL);
0552             program_multi_taps_filter(
0553                     xfm_dce,
0554                     data->taps.h_taps,
0555                     coeffs_h,
0556                     FILTER_TYPE_ALPHA_HORIZONTAL);
0557 
0558             xfm_dce->filter_v = coeffs_v;
0559             xfm_dce->filter_h = coeffs_h;
0560         }
0561     }
0562 
0563     /* 6. Program the viewport */
0564     program_viewport(xfm_dce, &data->viewport);
0565 
0566     /* DCE6 has no SCL_COEF_UPDATE_COMPLETE bit to flip to new coefficient memory */
0567 
0568     /* DCE6 DATA_FORMAT register does not support ALPHA_EN */
0569 }
0570 #endif
0571 
0572 /*****************************************************************************
0573  * set_clamp
0574  *
0575  * @param depth : bit depth to set the clamp to (should match denorm)
0576  *
0577  * @brief
0578  *     Programs clamp according to panel bit depth.
0579  *
0580  *******************************************************************************/
0581 static void set_clamp(
0582     struct dce_transform *xfm_dce,
0583     enum dc_color_depth depth)
0584 {
0585     int clamp_max = 0;
0586 
0587     /* At the clamp block the data will be MSB aligned, so we set the max
0588      * clamp accordingly.
0589      * For example, the max value for 6 bits MSB aligned (14 bit bus) would
0590      * be "11 1111 0000 0000" in binary, so 0x3F00.
0591      */
0592     switch (depth) {
0593     case COLOR_DEPTH_666:
0594         /* 6bit MSB aligned on 14 bit bus '11 1111 0000 0000' */
0595         clamp_max = 0x3F00;
0596         break;
0597     case COLOR_DEPTH_888:
0598         /* 8bit MSB aligned on 14 bit bus '11 1111 1100 0000' */
0599         clamp_max = 0x3FC0;
0600         break;
0601     case COLOR_DEPTH_101010:
0602         /* 10bit MSB aligned on 14 bit bus '11 1111 1111 0000' */
0603         clamp_max = 0x3FF0;
0604         break;
0605     case COLOR_DEPTH_121212:
0606         /* 12bit MSB aligned on 14 bit bus '11 1111 1111 1100' */
0607         clamp_max = 0x3FFC;
0608         break;
0609     default:
0610         clamp_max = 0x3FC0;
0611         BREAK_TO_DEBUGGER(); /* Invalid clamp bit depth */
0612     }
0613     REG_SET_2(OUT_CLAMP_CONTROL_B_CB, 0,
0614             OUT_CLAMP_MIN_B_CB, 0,
0615             OUT_CLAMP_MAX_B_CB, clamp_max);
0616 
0617     REG_SET_2(OUT_CLAMP_CONTROL_G_Y, 0,
0618             OUT_CLAMP_MIN_G_Y, 0,
0619             OUT_CLAMP_MAX_G_Y, clamp_max);
0620 
0621     REG_SET_2(OUT_CLAMP_CONTROL_R_CR, 0,
0622             OUT_CLAMP_MIN_R_CR, 0,
0623             OUT_CLAMP_MAX_R_CR, clamp_max);
0624 }
0625 
0626 /*******************************************************************************
0627  * set_round
0628  *
0629  * @brief
0630  *     Programs Round/Truncate
0631  *
0632  * @param [in] mode  :round or truncate
0633  * @param [in] depth :bit depth to round/truncate to
0634  OUT_ROUND_TRUNC_MODE 3:0 0xA Output data round or truncate mode
0635  POSSIBLE VALUES:
0636       00 - truncate to u0.12
0637       01 - truncate to u0.11
0638       02 - truncate to u0.10
0639       03 - truncate to u0.9
0640       04 - truncate to u0.8
0641       05 - reserved
0642       06 - truncate to u0.14
0643       07 - truncate to u0.13        set_reg_field_value(
0644             value,
0645             clamp_max,
0646             OUT_CLAMP_CONTROL_R_CR,
0647             OUT_CLAMP_MAX_R_CR);
0648       08 - round to u0.12
0649       09 - round to u0.11
0650       10 - round to u0.10
0651       11 - round to u0.9
0652       12 - round to u0.8
0653       13 - reserved
0654       14 - round to u0.14
0655       15 - round to u0.13
0656 
0657  ******************************************************************************/
0658 static void set_round(
0659     struct dce_transform *xfm_dce,
0660     enum dcp_out_trunc_round_mode mode,
0661     enum dcp_out_trunc_round_depth depth)
0662 {
0663     int depth_bits = 0;
0664     int mode_bit = 0;
0665 
0666     /*  set up bit depth */
0667     switch (depth) {
0668     case DCP_OUT_TRUNC_ROUND_DEPTH_14BIT:
0669         depth_bits = 6;
0670         break;
0671     case DCP_OUT_TRUNC_ROUND_DEPTH_13BIT:
0672         depth_bits = 7;
0673         break;
0674     case DCP_OUT_TRUNC_ROUND_DEPTH_12BIT:
0675         depth_bits = 0;
0676         break;
0677     case DCP_OUT_TRUNC_ROUND_DEPTH_11BIT:
0678         depth_bits = 1;
0679         break;
0680     case DCP_OUT_TRUNC_ROUND_DEPTH_10BIT:
0681         depth_bits = 2;
0682         break;
0683     case DCP_OUT_TRUNC_ROUND_DEPTH_9BIT:
0684         depth_bits = 3;
0685         break;
0686     case DCP_OUT_TRUNC_ROUND_DEPTH_8BIT:
0687         depth_bits = 4;
0688         break;
0689     default:
0690         depth_bits = 4;
0691         BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_depth */
0692     }
0693 
0694     /*  set up round or truncate */
0695     switch (mode) {
0696     case DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE:
0697         mode_bit = 0;
0698         break;
0699     case DCP_OUT_TRUNC_ROUND_MODE_ROUND:
0700         mode_bit = 1;
0701         break;
0702     default:
0703         BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_mode */
0704     }
0705 
0706     depth_bits |= mode_bit << 3;
0707 
0708     REG_SET(OUT_ROUND_CONTROL, 0, OUT_ROUND_TRUNC_MODE, depth_bits);
0709 }
0710 
0711 /*****************************************************************************
0712  * set_dither
0713  *
0714  * @brief
0715  *     Programs Dither
0716  *
0717  * @param [in] dither_enable        : enable dither
0718  * @param [in] dither_mode           : dither mode to set
0719  * @param [in] dither_depth          : bit depth to dither to
0720  * @param [in] frame_random_enable    : enable frame random
0721  * @param [in] rgb_random_enable      : enable rgb random
0722  * @param [in] highpass_random_enable : enable highpass random
0723  *
0724  ******************************************************************************/
0725 
0726 static void set_dither(
0727     struct dce_transform *xfm_dce,
0728     bool dither_enable,
0729     enum dcp_spatial_dither_mode dither_mode,
0730     enum dcp_spatial_dither_depth dither_depth,
0731     bool frame_random_enable,
0732     bool rgb_random_enable,
0733     bool highpass_random_enable)
0734 {
0735     int dither_depth_bits = 0;
0736     int dither_mode_bits = 0;
0737 
0738     switch (dither_mode) {
0739     case DCP_SPATIAL_DITHER_MODE_AAAA:
0740         dither_mode_bits = 0;
0741         break;
0742     case DCP_SPATIAL_DITHER_MODE_A_AA_A:
0743         dither_mode_bits = 1;
0744         break;
0745     case DCP_SPATIAL_DITHER_MODE_AABBAABB:
0746         dither_mode_bits = 2;
0747         break;
0748     case DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC:
0749         dither_mode_bits = 3;
0750         break;
0751     default:
0752         /* Invalid dcp_spatial_dither_mode */
0753         BREAK_TO_DEBUGGER();
0754     }
0755 
0756     switch (dither_depth) {
0757     case DCP_SPATIAL_DITHER_DEPTH_30BPP:
0758         dither_depth_bits = 0;
0759         break;
0760     case DCP_SPATIAL_DITHER_DEPTH_24BPP:
0761         dither_depth_bits = 1;
0762         break;
0763     default:
0764         /* Invalid dcp_spatial_dither_depth */
0765         BREAK_TO_DEBUGGER();
0766     }
0767 
0768     /*  write the register */
0769     REG_SET_6(DCP_SPATIAL_DITHER_CNTL, 0,
0770             DCP_SPATIAL_DITHER_EN, dither_enable,
0771             DCP_SPATIAL_DITHER_MODE, dither_mode_bits,
0772             DCP_SPATIAL_DITHER_DEPTH, dither_depth_bits,
0773             DCP_FRAME_RANDOM_ENABLE, frame_random_enable,
0774             DCP_RGB_RANDOM_ENABLE, rgb_random_enable,
0775             DCP_HIGHPASS_RANDOM_ENABLE, highpass_random_enable);
0776 }
0777 
0778 /*****************************************************************************
0779  * dce_transform_bit_depth_reduction_program
0780  *
0781  * @brief
0782  *     Programs the DCP bit depth reduction registers (Clamp, Round/Truncate,
0783  *      Dither) for dce
0784  *
0785  * @param depth : bit depth to set the clamp to (should match denorm)
0786  *
0787  ******************************************************************************/
0788 static void program_bit_depth_reduction(
0789     struct dce_transform *xfm_dce,
0790     enum dc_color_depth depth,
0791     const struct bit_depth_reduction_params *bit_depth_params)
0792 {
0793     enum dcp_out_trunc_round_depth trunc_round_depth;
0794     enum dcp_out_trunc_round_mode trunc_mode;
0795     bool spatial_dither_enable;
0796 
0797     ASSERT(depth <= COLOR_DEPTH_121212); /* Invalid clamp bit depth */
0798 
0799     spatial_dither_enable = bit_depth_params->flags.SPATIAL_DITHER_ENABLED;
0800     /* Default to 12 bit truncation without rounding */
0801     trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT;
0802     trunc_mode = DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE;
0803 
0804     if (bit_depth_params->flags.TRUNCATE_ENABLED) {
0805         /* Don't enable dithering if truncation is enabled */
0806         spatial_dither_enable = false;
0807         trunc_mode = bit_depth_params->flags.TRUNCATE_MODE ?
0808                  DCP_OUT_TRUNC_ROUND_MODE_ROUND :
0809                  DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE;
0810 
0811         if (bit_depth_params->flags.TRUNCATE_DEPTH == 0 ||
0812             bit_depth_params->flags.TRUNCATE_DEPTH == 1)
0813             trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_8BIT;
0814         else if (bit_depth_params->flags.TRUNCATE_DEPTH == 2)
0815             trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_10BIT;
0816         else {
0817             /*
0818              * Invalid truncate/round depth. Setting here to 12bit
0819              * to prevent use-before-initialize errors.
0820              */
0821             trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT;
0822             BREAK_TO_DEBUGGER();
0823         }
0824     }
0825 
0826     set_clamp(xfm_dce, depth);
0827     set_round(xfm_dce, trunc_mode, trunc_round_depth);
0828     set_dither(xfm_dce,
0829            spatial_dither_enable,
0830            DCP_SPATIAL_DITHER_MODE_A_AA_A,
0831            DCP_SPATIAL_DITHER_DEPTH_30BPP,
0832            bit_depth_params->flags.FRAME_RANDOM,
0833            bit_depth_params->flags.RGB_RANDOM,
0834            bit_depth_params->flags.HIGHPASS_RANDOM);
0835 }
0836 
0837 #if defined(CONFIG_DRM_AMD_DC_SI)
0838 /*****************************************************************************
0839  * dce60_transform_bit_depth_reduction program
0840  *
0841  * @brief
0842  *     Programs the DCP bit depth reduction registers (Clamp, Round/Truncate,
0843  *      Dither) for dce
0844  *
0845  * @param depth : bit depth to set the clamp to (should match denorm)
0846  *
0847  ******************************************************************************/
0848 static void dce60_program_bit_depth_reduction(
0849     struct dce_transform *xfm_dce,
0850     enum dc_color_depth depth,
0851     const struct bit_depth_reduction_params *bit_depth_params)
0852 {
0853     enum dcp_out_trunc_round_depth trunc_round_depth;
0854     enum dcp_out_trunc_round_mode trunc_mode;
0855     bool spatial_dither_enable;
0856 
0857     ASSERT(depth <= COLOR_DEPTH_121212); /* Invalid clamp bit depth */
0858 
0859     spatial_dither_enable = bit_depth_params->flags.SPATIAL_DITHER_ENABLED;
0860     /* Default to 12 bit truncation without rounding */
0861     trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT;
0862     trunc_mode = DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE;
0863 
0864     if (bit_depth_params->flags.TRUNCATE_ENABLED) {
0865         /* Don't enable dithering if truncation is enabled */
0866         spatial_dither_enable = false;
0867         trunc_mode = bit_depth_params->flags.TRUNCATE_MODE ?
0868                  DCP_OUT_TRUNC_ROUND_MODE_ROUND :
0869                  DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE;
0870 
0871         if (bit_depth_params->flags.TRUNCATE_DEPTH == 0 ||
0872             bit_depth_params->flags.TRUNCATE_DEPTH == 1)
0873             trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_8BIT;
0874         else if (bit_depth_params->flags.TRUNCATE_DEPTH == 2)
0875             trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_10BIT;
0876         else {
0877             /*
0878              * Invalid truncate/round depth. Setting here to 12bit
0879              * to prevent use-before-initialize errors.
0880              */
0881             trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT;
0882             BREAK_TO_DEBUGGER();
0883         }
0884     }
0885 
0886     /* DCE6 has no OUT_CLAMP_CONTROL_* registers - set_clamp() is skipped */
0887     set_round(xfm_dce, trunc_mode, trunc_round_depth);
0888     set_dither(xfm_dce,
0889            spatial_dither_enable,
0890            DCP_SPATIAL_DITHER_MODE_A_AA_A,
0891            DCP_SPATIAL_DITHER_DEPTH_30BPP,
0892            bit_depth_params->flags.FRAME_RANDOM,
0893            bit_depth_params->flags.RGB_RANDOM,
0894            bit_depth_params->flags.HIGHPASS_RANDOM);
0895 }
0896 #endif
0897 
0898 static int dce_transform_get_max_num_of_supported_lines(
0899     struct dce_transform *xfm_dce,
0900     enum lb_pixel_depth depth,
0901     int pixel_width)
0902 {
0903     int pixels_per_entries = 0;
0904     int max_pixels_supports = 0;
0905 
0906     ASSERT(pixel_width);
0907 
0908     /* Find number of pixels that can fit into a single LB entry and
0909      * take floor of the value since we cannot store a single pixel
0910      * across multiple entries. */
0911     switch (depth) {
0912     case LB_PIXEL_DEPTH_18BPP:
0913         pixels_per_entries = xfm_dce->lb_bits_per_entry / 18;
0914         break;
0915 
0916     case LB_PIXEL_DEPTH_24BPP:
0917         pixels_per_entries = xfm_dce->lb_bits_per_entry / 24;
0918         break;
0919 
0920     case LB_PIXEL_DEPTH_30BPP:
0921         pixels_per_entries = xfm_dce->lb_bits_per_entry / 30;
0922         break;
0923 
0924     case LB_PIXEL_DEPTH_36BPP:
0925         pixels_per_entries = xfm_dce->lb_bits_per_entry / 36;
0926         break;
0927 
0928     default:
0929         DC_LOG_WARNING("%s: Invalid LB pixel depth",
0930             __func__);
0931         BREAK_TO_DEBUGGER();
0932         break;
0933     }
0934 
0935     ASSERT(pixels_per_entries);
0936 
0937     max_pixels_supports =
0938             pixels_per_entries *
0939             xfm_dce->lb_memory_size;
0940 
0941     return (max_pixels_supports / pixel_width);
0942 }
0943 
0944 static void set_denormalization(
0945     struct dce_transform *xfm_dce,
0946     enum dc_color_depth depth)
0947 {
0948     int denorm_mode = 0;
0949 
0950     switch (depth) {
0951     case COLOR_DEPTH_666:
0952         /* 63/64 for 6 bit output color depth */
0953         denorm_mode = 1;
0954         break;
0955     case COLOR_DEPTH_888:
0956         /* Unity for 8 bit output color depth
0957          * because prescale is disabled by default */
0958         denorm_mode = 0;
0959         break;
0960     case COLOR_DEPTH_101010:
0961         /* 1023/1024 for 10 bit output color depth */
0962         denorm_mode = 3;
0963         break;
0964     case COLOR_DEPTH_121212:
0965         /* 4095/4096 for 12 bit output color depth */
0966         denorm_mode = 5;
0967         break;
0968     case COLOR_DEPTH_141414:
0969     case COLOR_DEPTH_161616:
0970     default:
0971         /* not valid used case! */
0972         break;
0973     }
0974 
0975     REG_SET(DENORM_CONTROL, 0, DENORM_MODE, denorm_mode);
0976 }
0977 
0978 static void dce_transform_set_pixel_storage_depth(
0979     struct transform *xfm,
0980     enum lb_pixel_depth depth,
0981     const struct bit_depth_reduction_params *bit_depth_params)
0982 {
0983     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
0984     int pixel_depth, expan_mode;
0985     enum dc_color_depth color_depth;
0986 
0987     switch (depth) {
0988     case LB_PIXEL_DEPTH_18BPP:
0989         color_depth = COLOR_DEPTH_666;
0990         pixel_depth = 2;
0991         expan_mode  = 1;
0992         break;
0993     case LB_PIXEL_DEPTH_24BPP:
0994         color_depth = COLOR_DEPTH_888;
0995         pixel_depth = 1;
0996         expan_mode  = 1;
0997         break;
0998     case LB_PIXEL_DEPTH_30BPP:
0999         color_depth = COLOR_DEPTH_101010;
1000         pixel_depth = 0;
1001         expan_mode  = 1;
1002         break;
1003     case LB_PIXEL_DEPTH_36BPP:
1004         color_depth = COLOR_DEPTH_121212;
1005         pixel_depth = 3;
1006         expan_mode  = 0;
1007         break;
1008     default:
1009         color_depth = COLOR_DEPTH_101010;
1010         pixel_depth = 0;
1011         expan_mode  = 1;
1012         BREAK_TO_DEBUGGER();
1013         break;
1014     }
1015 
1016     set_denormalization(xfm_dce, color_depth);
1017     program_bit_depth_reduction(xfm_dce, color_depth, bit_depth_params);
1018 
1019     REG_UPDATE_2(LB_DATA_FORMAT,
1020             PIXEL_DEPTH, pixel_depth,
1021             PIXEL_EXPAN_MODE, expan_mode);
1022 
1023     if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
1024         /*we should use unsupported capabilities
1025          *  unless it is required by w/a*/
1026         DC_LOG_WARNING("%s: Capability not supported",
1027             __func__);
1028     }
1029 }
1030 
1031 #if defined(CONFIG_DRM_AMD_DC_SI)
1032 static void dce60_transform_set_pixel_storage_depth(
1033     struct transform *xfm,
1034     enum lb_pixel_depth depth,
1035     const struct bit_depth_reduction_params *bit_depth_params)
1036 {
1037     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1038     enum dc_color_depth color_depth;
1039 
1040     switch (depth) {
1041     case LB_PIXEL_DEPTH_18BPP:
1042         color_depth = COLOR_DEPTH_666;
1043         break;
1044     case LB_PIXEL_DEPTH_24BPP:
1045         color_depth = COLOR_DEPTH_888;
1046         break;
1047     case LB_PIXEL_DEPTH_30BPP:
1048         color_depth = COLOR_DEPTH_101010;
1049         break;
1050     case LB_PIXEL_DEPTH_36BPP:
1051         color_depth = COLOR_DEPTH_121212;
1052         break;
1053     default:
1054         color_depth = COLOR_DEPTH_101010;
1055         BREAK_TO_DEBUGGER();
1056         break;
1057     }
1058 
1059     set_denormalization(xfm_dce, color_depth);
1060     dce60_program_bit_depth_reduction(xfm_dce, color_depth, bit_depth_params);
1061 
1062     /* DATA_FORMAT in DCE6 does not have PIXEL_DEPTH and PIXEL_EXPAN_MODE masks */
1063 
1064     if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
1065         /*we should use unsupported capabilities
1066          *  unless it is required by w/a*/
1067         DC_LOG_WARNING("%s: Capability not supported",
1068             __func__);
1069     }
1070 }
1071 #endif
1072 
1073 static void program_gamut_remap(
1074     struct dce_transform *xfm_dce,
1075     const uint16_t *reg_val)
1076 {
1077     if (reg_val) {
1078         REG_SET_2(GAMUT_REMAP_C11_C12, 0,
1079                 GAMUT_REMAP_C11, reg_val[0],
1080                 GAMUT_REMAP_C12, reg_val[1]);
1081         REG_SET_2(GAMUT_REMAP_C13_C14, 0,
1082                 GAMUT_REMAP_C13, reg_val[2],
1083                 GAMUT_REMAP_C14, reg_val[3]);
1084         REG_SET_2(GAMUT_REMAP_C21_C22, 0,
1085                 GAMUT_REMAP_C21, reg_val[4],
1086                 GAMUT_REMAP_C22, reg_val[5]);
1087         REG_SET_2(GAMUT_REMAP_C23_C24, 0,
1088                 GAMUT_REMAP_C23, reg_val[6],
1089                 GAMUT_REMAP_C24, reg_val[7]);
1090         REG_SET_2(GAMUT_REMAP_C31_C32, 0,
1091                 GAMUT_REMAP_C31, reg_val[8],
1092                 GAMUT_REMAP_C32, reg_val[9]);
1093         REG_SET_2(GAMUT_REMAP_C33_C34, 0,
1094                 GAMUT_REMAP_C33, reg_val[10],
1095                 GAMUT_REMAP_C34, reg_val[11]);
1096 
1097         REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 1);
1098     } else
1099         REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 0);
1100 
1101 }
1102 
1103 /*
1104  *****************************************************************************
1105  *  Function: dal_transform_wide_gamut_set_gamut_remap
1106  *
1107  *  @param [in] const struct xfm_grph_csc_adjustment *adjust
1108  *
1109  *  @return
1110  *     void
1111  *
1112  *  @note calculate and apply color temperature adjustment to in Rgb color space
1113  *
1114  *  @see
1115  *
1116  *****************************************************************************
1117  */
1118 static void dce_transform_set_gamut_remap(
1119     struct transform *xfm,
1120     const struct xfm_grph_csc_adjustment *adjust)
1121 {
1122     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1123     int i = 0;
1124 
1125     if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
1126         /* Bypass if type is bypass or hw */
1127         program_gamut_remap(xfm_dce, NULL);
1128     else {
1129         struct fixed31_32 arr_matrix[GAMUT_MATRIX_SIZE];
1130         uint16_t arr_reg_val[GAMUT_MATRIX_SIZE];
1131 
1132         for (i = 0; i < GAMUT_MATRIX_SIZE; i++)
1133             arr_matrix[i] = adjust->temperature_matrix[i];
1134 
1135         convert_float_matrix(
1136             arr_reg_val, arr_matrix, GAMUT_MATRIX_SIZE);
1137 
1138         program_gamut_remap(xfm_dce, arr_reg_val);
1139     }
1140 }
1141 
1142 static uint32_t decide_taps(struct fixed31_32 ratio, uint32_t in_taps, bool chroma)
1143 {
1144     uint32_t taps;
1145 
1146     if (IDENTITY_RATIO(ratio)) {
1147         return 1;
1148     } else if (in_taps != 0) {
1149         taps = in_taps;
1150     } else {
1151         taps = 4;
1152     }
1153 
1154     if (chroma) {
1155         taps /= 2;
1156         if (taps < 2)
1157             taps = 2;
1158     }
1159 
1160     return taps;
1161 }
1162 
1163 
1164 bool dce_transform_get_optimal_number_of_taps(
1165     struct transform *xfm,
1166     struct scaler_data *scl_data,
1167     const struct scaling_taps *in_taps)
1168 {
1169     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1170     int pixel_width = scl_data->viewport.width;
1171     int max_num_of_lines;
1172 
1173     if (xfm_dce->prescaler_on &&
1174             (scl_data->viewport.width > scl_data->recout.width))
1175         pixel_width = scl_data->recout.width;
1176 
1177     max_num_of_lines = dce_transform_get_max_num_of_supported_lines(
1178         xfm_dce,
1179         scl_data->lb_params.depth,
1180         pixel_width);
1181 
1182     /* Fail if in_taps are impossible */
1183     if (in_taps->v_taps >= max_num_of_lines)
1184         return false;
1185 
1186     /*
1187      * Set taps according to this policy (in this order)
1188      * - Use 1 for no scaling
1189      * - Use input taps
1190      * - Use 4 and reduce as required by line buffer size
1191      * - Decide chroma taps if chroma is scaled
1192      *
1193      * Ignore input chroma taps. Decide based on non-chroma
1194      */
1195     scl_data->taps.h_taps = decide_taps(scl_data->ratios.horz, in_taps->h_taps, false);
1196     scl_data->taps.v_taps = decide_taps(scl_data->ratios.vert, in_taps->v_taps, false);
1197     scl_data->taps.h_taps_c = decide_taps(scl_data->ratios.horz_c, in_taps->h_taps, true);
1198     scl_data->taps.v_taps_c = decide_taps(scl_data->ratios.vert_c, in_taps->v_taps, true);
1199 
1200     if (!IDENTITY_RATIO(scl_data->ratios.vert)) {
1201         /* reduce v_taps if needed but ensure we have at least two */
1202         if (in_taps->v_taps == 0
1203                 && max_num_of_lines <= scl_data->taps.v_taps
1204                 && scl_data->taps.v_taps > 1) {
1205             scl_data->taps.v_taps = max_num_of_lines - 1;
1206         }
1207 
1208         if (scl_data->taps.v_taps <= 1)
1209             return false;
1210     }
1211 
1212     if (!IDENTITY_RATIO(scl_data->ratios.vert_c)) {
1213         /* reduce chroma v_taps if needed but ensure we have at least two */
1214         if (max_num_of_lines <= scl_data->taps.v_taps_c && scl_data->taps.v_taps_c > 1) {
1215             scl_data->taps.v_taps_c = max_num_of_lines - 1;
1216         }
1217 
1218         if (scl_data->taps.v_taps_c <= 1)
1219             return false;
1220     }
1221 
1222     /* we've got valid taps */
1223     return true;
1224 }
1225 
1226 static void dce_transform_reset(struct transform *xfm)
1227 {
1228     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1229 
1230     xfm_dce->filter_h = NULL;
1231     xfm_dce->filter_v = NULL;
1232 }
1233 
1234 static void program_color_matrix(
1235     struct dce_transform *xfm_dce,
1236     const struct out_csc_color_matrix *tbl_entry,
1237     enum grph_color_adjust_option options)
1238 {
1239     {
1240         REG_SET_2(OUTPUT_CSC_C11_C12, 0,
1241             OUTPUT_CSC_C11, tbl_entry->regval[0],
1242             OUTPUT_CSC_C12, tbl_entry->regval[1]);
1243     }
1244     {
1245         REG_SET_2(OUTPUT_CSC_C13_C14, 0,
1246             OUTPUT_CSC_C11, tbl_entry->regval[2],
1247             OUTPUT_CSC_C12, tbl_entry->regval[3]);
1248     }
1249     {
1250         REG_SET_2(OUTPUT_CSC_C21_C22, 0,
1251             OUTPUT_CSC_C11, tbl_entry->regval[4],
1252             OUTPUT_CSC_C12, tbl_entry->regval[5]);
1253     }
1254     {
1255         REG_SET_2(OUTPUT_CSC_C23_C24, 0,
1256             OUTPUT_CSC_C11, tbl_entry->regval[6],
1257             OUTPUT_CSC_C12, tbl_entry->regval[7]);
1258     }
1259     {
1260         REG_SET_2(OUTPUT_CSC_C31_C32, 0,
1261             OUTPUT_CSC_C11, tbl_entry->regval[8],
1262             OUTPUT_CSC_C12, tbl_entry->regval[9]);
1263     }
1264     {
1265         REG_SET_2(OUTPUT_CSC_C33_C34, 0,
1266             OUTPUT_CSC_C11, tbl_entry->regval[10],
1267             OUTPUT_CSC_C12, tbl_entry->regval[11]);
1268     }
1269 }
1270 
1271 static bool configure_graphics_mode(
1272     struct dce_transform *xfm_dce,
1273     enum csc_color_mode config,
1274     enum graphics_csc_adjust_type csc_adjust_type,
1275     enum dc_color_space color_space)
1276 {
1277     REG_SET(OUTPUT_CSC_CONTROL, 0,
1278         OUTPUT_CSC_GRPH_MODE, 0);
1279 
1280     if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) {
1281         if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) {
1282             REG_SET(OUTPUT_CSC_CONTROL, 0,
1283                 OUTPUT_CSC_GRPH_MODE, 4);
1284         } else {
1285 
1286             switch (color_space) {
1287             case COLOR_SPACE_SRGB:
1288                 /* by pass */
1289                 REG_SET(OUTPUT_CSC_CONTROL, 0,
1290                     OUTPUT_CSC_GRPH_MODE, 0);
1291                 break;
1292             case COLOR_SPACE_SRGB_LIMITED:
1293                 /* TV RGB */
1294                 REG_SET(OUTPUT_CSC_CONTROL, 0,
1295                     OUTPUT_CSC_GRPH_MODE, 1);
1296                 break;
1297             case COLOR_SPACE_YCBCR601:
1298             case COLOR_SPACE_YCBCR601_LIMITED:
1299                 /* YCbCr601 */
1300                 REG_SET(OUTPUT_CSC_CONTROL, 0,
1301                     OUTPUT_CSC_GRPH_MODE, 2);
1302                 break;
1303             case COLOR_SPACE_YCBCR709:
1304             case COLOR_SPACE_YCBCR709_LIMITED:
1305                 /* YCbCr709 */
1306                 REG_SET(OUTPUT_CSC_CONTROL, 0,
1307                     OUTPUT_CSC_GRPH_MODE, 3);
1308                 break;
1309             default:
1310                 return false;
1311             }
1312         }
1313     } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) {
1314         switch (color_space) {
1315         case COLOR_SPACE_SRGB:
1316             /* by pass */
1317             REG_SET(OUTPUT_CSC_CONTROL, 0,
1318                 OUTPUT_CSC_GRPH_MODE, 0);
1319             break;
1320         case COLOR_SPACE_SRGB_LIMITED:
1321             /* TV RGB */
1322             REG_SET(OUTPUT_CSC_CONTROL, 0,
1323                 OUTPUT_CSC_GRPH_MODE, 1);
1324             break;
1325         case COLOR_SPACE_YCBCR601:
1326         case COLOR_SPACE_YCBCR601_LIMITED:
1327             /* YCbCr601 */
1328             REG_SET(OUTPUT_CSC_CONTROL, 0,
1329                 OUTPUT_CSC_GRPH_MODE, 2);
1330             break;
1331         case COLOR_SPACE_YCBCR709:
1332         case COLOR_SPACE_YCBCR709_LIMITED:
1333              /* YCbCr709 */
1334             REG_SET(OUTPUT_CSC_CONTROL, 0,
1335                 OUTPUT_CSC_GRPH_MODE, 3);
1336             break;
1337         default:
1338             return false;
1339         }
1340 
1341     } else
1342         /* by pass */
1343         REG_SET(OUTPUT_CSC_CONTROL, 0,
1344             OUTPUT_CSC_GRPH_MODE, 0);
1345 
1346     return true;
1347 }
1348 
1349 void dce110_opp_set_csc_adjustment(
1350     struct transform *xfm,
1351     const struct out_csc_color_matrix *tbl_entry)
1352 {
1353     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1354     enum csc_color_mode config =
1355             CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
1356 
1357     program_color_matrix(
1358             xfm_dce, tbl_entry, GRPH_COLOR_MATRIX_SW);
1359 
1360     /*  We did everything ,now program DxOUTPUT_CSC_CONTROL */
1361     configure_graphics_mode(xfm_dce, config, GRAPHICS_CSC_ADJUST_TYPE_SW,
1362             tbl_entry->color_space);
1363 }
1364 
1365 void dce110_opp_set_csc_default(
1366     struct transform *xfm,
1367     const struct default_adjustment *default_adjust)
1368 {
1369     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1370     enum csc_color_mode config =
1371             CSC_COLOR_MODE_GRAPHICS_PREDEFINED;
1372 
1373     if (default_adjust->force_hw_default == false) {
1374         const struct out_csc_color_matrix *elm;
1375         /* currently parameter not in use */
1376         enum grph_color_adjust_option option =
1377             GRPH_COLOR_MATRIX_HW_DEFAULT;
1378         uint32_t i;
1379         /*
1380          * HW default false we program locally defined matrix
1381          * HW default true  we use predefined hw matrix and we
1382          * do not need to program matrix
1383          * OEM wants the HW default via runtime parameter.
1384          */
1385         option = GRPH_COLOR_MATRIX_SW;
1386 
1387         for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) {
1388             elm = &global_color_matrix[i];
1389             if (elm->color_space != default_adjust->out_color_space)
1390                 continue;
1391             /* program the matrix with default values from this
1392              * file */
1393             program_color_matrix(xfm_dce, elm, option);
1394             config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
1395             break;
1396         }
1397     }
1398 
1399     /* configure the what we programmed :
1400      * 1. Default values from this file
1401      * 2. Use hardware default from ROM_A and we do not need to program
1402      * matrix */
1403 
1404     configure_graphics_mode(xfm_dce, config,
1405         default_adjust->csc_adjust_type,
1406         default_adjust->out_color_space);
1407 }
1408 
1409 static void program_pwl(struct dce_transform *xfm_dce,
1410             const struct pwl_params *params)
1411 {
1412     int retval;
1413     uint8_t max_tries = 10;
1414     uint8_t counter = 0;
1415     uint32_t i = 0;
1416     const struct pwl_result_data *rgb = params->rgb_resulted;
1417 
1418     /* Power on LUT memory */
1419     if (REG(DCFE_MEM_PWR_CTRL))
1420         REG_UPDATE(DCFE_MEM_PWR_CTRL,
1421                DCP_REGAMMA_MEM_PWR_DIS, 1);
1422     else
1423         REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL,
1424                REGAMMA_LUT_LIGHT_SLEEP_DIS, 1);
1425 
1426     while (counter < max_tries) {
1427         if (REG(DCFE_MEM_PWR_STATUS)) {
1428             REG_GET(DCFE_MEM_PWR_STATUS,
1429                 DCP_REGAMMA_MEM_PWR_STATE,
1430                 &retval);
1431 
1432             if (retval == 0)
1433                 break;
1434             ++counter;
1435         } else {
1436             REG_GET(DCFE_MEM_LIGHT_SLEEP_CNTL,
1437                 REGAMMA_LUT_MEM_PWR_STATE,
1438                 &retval);
1439 
1440             if (retval == 0)
1441                 break;
1442             ++counter;
1443         }
1444     }
1445 
1446     if (counter == max_tries) {
1447         DC_LOG_WARNING("%s: regamma lut was not powered on "
1448                 "in a timely manner,"
1449                 " programming still proceeds\n",
1450                 __func__);
1451     }
1452 
1453     REG_UPDATE(REGAMMA_LUT_WRITE_EN_MASK,
1454            REGAMMA_LUT_WRITE_EN_MASK, 7);
1455 
1456     REG_WRITE(REGAMMA_LUT_INDEX, 0);
1457 
1458     /* Program REGAMMA_LUT_DATA */
1459     while (i != params->hw_points_num) {
1460 
1461         REG_WRITE(REGAMMA_LUT_DATA, rgb->red_reg);
1462         REG_WRITE(REGAMMA_LUT_DATA, rgb->green_reg);
1463         REG_WRITE(REGAMMA_LUT_DATA, rgb->blue_reg);
1464         REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_red_reg);
1465         REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_green_reg);
1466         REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_blue_reg);
1467 
1468         ++rgb;
1469         ++i;
1470     }
1471 
1472     /*  we are done with DCP LUT memory; re-enable low power mode */
1473     if (REG(DCFE_MEM_PWR_CTRL))
1474         REG_UPDATE(DCFE_MEM_PWR_CTRL,
1475                DCP_REGAMMA_MEM_PWR_DIS, 0);
1476     else
1477         REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL,
1478                REGAMMA_LUT_LIGHT_SLEEP_DIS, 0);
1479 }
1480 
1481 static void regamma_config_regions_and_segments(struct dce_transform *xfm_dce,
1482                         const struct pwl_params *params)
1483 {
1484     const struct gamma_curve *curve;
1485 
1486     REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0,
1487           REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x,
1488           REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0);
1489 
1490     REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0,
1491         REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope);
1492 
1493     REG_SET(REGAMMA_CNTLA_END_CNTL1, 0,
1494         REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x);
1495 
1496     REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0,
1497           REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[1].custom_float_y,
1498           REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[1].custom_float_slope);
1499 
1500     curve = params->arr_curve_points;
1501 
1502     REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0,
1503           REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1504           REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1505           REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1506           REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1507     curve += 2;
1508 
1509     REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0,
1510           REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1511           REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1512           REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1513           REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1514     curve += 2;
1515 
1516     REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0,
1517           REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1518           REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1519           REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1520           REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1521     curve += 2;
1522 
1523     REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0,
1524           REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1525           REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1526           REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1527           REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1528     curve += 2;
1529 
1530     REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0,
1531           REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1532           REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1533           REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1534           REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1535     curve += 2;
1536 
1537     REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0,
1538           REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1539           REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1540           REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1541           REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1542     curve += 2;
1543 
1544     REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0,
1545           REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1546           REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1547           REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1548           REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1549     curve += 2;
1550 
1551     REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0,
1552           REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1553           REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1554           REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1555           REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1556 }
1557 
1558 
1559 
1560 void dce110_opp_program_regamma_pwl(struct transform *xfm,
1561                     const struct pwl_params *params)
1562 {
1563     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1564 
1565     /* Setup regions */
1566     regamma_config_regions_and_segments(xfm_dce, params);
1567 
1568     /* Program PWL */
1569     program_pwl(xfm_dce, params);
1570 }
1571 
1572 void dce110_opp_power_on_regamma_lut(struct transform *xfm,
1573                      bool power_on)
1574 {
1575     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1576 
1577     if (REG(DCFE_MEM_PWR_CTRL))
1578         REG_UPDATE_2(DCFE_MEM_PWR_CTRL,
1579                  DCP_REGAMMA_MEM_PWR_DIS, power_on,
1580                  DCP_LUT_MEM_PWR_DIS, power_on);
1581     else
1582         REG_UPDATE_2(DCFE_MEM_LIGHT_SLEEP_CNTL,
1583                 REGAMMA_LUT_LIGHT_SLEEP_DIS, power_on,
1584                 DCP_LUT_LIGHT_SLEEP_DIS, power_on);
1585 
1586 }
1587 
1588 void dce110_opp_set_regamma_mode(struct transform *xfm,
1589                  enum opp_regamma mode)
1590 {
1591     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1592 
1593     REG_SET(REGAMMA_CONTROL, 0,
1594         GRPH_REGAMMA_MODE, mode);
1595 }
1596 
1597 static const struct transform_funcs dce_transform_funcs = {
1598     .transform_reset = dce_transform_reset,
1599     .transform_set_scaler = dce_transform_set_scaler,
1600     .transform_set_gamut_remap = dce_transform_set_gamut_remap,
1601     .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment,
1602     .opp_set_csc_default = dce110_opp_set_csc_default,
1603     .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut,
1604     .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl,
1605     .opp_set_regamma_mode = dce110_opp_set_regamma_mode,
1606     .transform_set_pixel_storage_depth = dce_transform_set_pixel_storage_depth,
1607     .transform_get_optimal_number_of_taps = dce_transform_get_optimal_number_of_taps
1608 };
1609 
1610 #if defined(CONFIG_DRM_AMD_DC_SI)
1611 static const struct transform_funcs dce60_transform_funcs = {
1612     .transform_reset = dce_transform_reset,
1613     .transform_set_scaler = dce60_transform_set_scaler,
1614     .transform_set_gamut_remap = dce_transform_set_gamut_remap,
1615     .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment,
1616     .opp_set_csc_default = dce110_opp_set_csc_default,
1617     .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut,
1618     .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl,
1619     .opp_set_regamma_mode = dce110_opp_set_regamma_mode,
1620     .transform_set_pixel_storage_depth = dce60_transform_set_pixel_storage_depth,
1621     .transform_get_optimal_number_of_taps = dce_transform_get_optimal_number_of_taps
1622 };
1623 #endif
1624 
1625 /*****************************************/
1626 /* Constructor, Destructor               */
1627 /*****************************************/
1628 
1629 void dce_transform_construct(
1630     struct dce_transform *xfm_dce,
1631     struct dc_context *ctx,
1632     uint32_t inst,
1633     const struct dce_transform_registers *regs,
1634     const struct dce_transform_shift *xfm_shift,
1635     const struct dce_transform_mask *xfm_mask)
1636 {
1637     xfm_dce->base.ctx = ctx;
1638 
1639     xfm_dce->base.inst = inst;
1640     xfm_dce->base.funcs = &dce_transform_funcs;
1641 
1642     xfm_dce->regs = regs;
1643     xfm_dce->xfm_shift = xfm_shift;
1644     xfm_dce->xfm_mask = xfm_mask;
1645 
1646     xfm_dce->prescaler_on = true;
1647     xfm_dce->lb_pixel_depth_supported =
1648             LB_PIXEL_DEPTH_18BPP |
1649             LB_PIXEL_DEPTH_24BPP |
1650             LB_PIXEL_DEPTH_30BPP |
1651             LB_PIXEL_DEPTH_36BPP;
1652 
1653     xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY;
1654     xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/
1655 }
1656 
1657 #if defined(CONFIG_DRM_AMD_DC_SI)
1658 void dce60_transform_construct(
1659     struct dce_transform *xfm_dce,
1660     struct dc_context *ctx,
1661     uint32_t inst,
1662     const struct dce_transform_registers *regs,
1663     const struct dce_transform_shift *xfm_shift,
1664     const struct dce_transform_mask *xfm_mask)
1665 {
1666     xfm_dce->base.ctx = ctx;
1667 
1668     xfm_dce->base.inst = inst;
1669     xfm_dce->base.funcs = &dce60_transform_funcs;
1670 
1671     xfm_dce->regs = regs;
1672     xfm_dce->xfm_shift = xfm_shift;
1673     xfm_dce->xfm_mask = xfm_mask;
1674 
1675     xfm_dce->prescaler_on = true;
1676     xfm_dce->lb_pixel_depth_supported =
1677             LB_PIXEL_DEPTH_18BPP |
1678             LB_PIXEL_DEPTH_24BPP |
1679             LB_PIXEL_DEPTH_30BPP |
1680             LB_PIXEL_DEPTH_36BPP;
1681 
1682     xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY;
1683     xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/
1684 }
1685 #endif