Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-15 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 "dm_services.h"
0027 #include "basics/conversion.h"
0028 
0029 #include "dce_opp.h"
0030 
0031 #include "reg_helper.h"
0032 
0033 #define REG(reg)\
0034     (opp110->regs->reg)
0035 
0036 #undef FN
0037 #define FN(reg_name, field_name) \
0038     opp110->opp_shift->field_name, opp110->opp_mask->field_name
0039 
0040 #define CTX \
0041     opp110->base.ctx
0042 
0043 enum {
0044     MAX_PWL_ENTRY = 128,
0045     MAX_REGIONS_NUMBER = 16
0046 };
0047 
0048 enum {
0049     MAX_LUT_ENTRY = 256,
0050     MAX_NUMBER_OF_ENTRIES = 256
0051 };
0052 
0053 
0054 enum {
0055     OUTPUT_CSC_MATRIX_SIZE = 12
0056 };
0057 
0058 
0059 
0060 
0061 
0062 
0063 
0064 
0065 
0066 
0067 
0068 
0069 
0070 
0071 
0072 
0073 
0074 
0075 
0076 
0077 
0078 
0079 /*
0080  *****************************************************************************
0081  *  Function: regamma_config_regions_and_segments
0082  *
0083  *     build regamma curve by using predefined hw points
0084  *     uses interface parameters ,like EDID coeff.
0085  *
0086  * @param   : parameters   interface parameters
0087  *  @return void
0088  *
0089  *  @note
0090  *
0091  *  @see
0092  *
0093  *****************************************************************************
0094  */
0095 
0096 
0097 
0098 /*
0099  *  set_truncation
0100  *  1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
0101  *  2) enable truncation
0102  *  3) HW remove 12bit FMT support for DCE11 power saving reason.
0103  */
0104 static void set_truncation(
0105         struct dce110_opp *opp110,
0106         const struct bit_depth_reduction_params *params)
0107 {
0108     /*Disable truncation*/
0109     REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
0110             FMT_TRUNCATE_EN, 0,
0111             FMT_TRUNCATE_DEPTH, 0,
0112             FMT_TRUNCATE_MODE, 0);
0113 
0114 
0115     if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
0116         /*  8bpc trunc on YCbCr422*/
0117         if (params->flags.TRUNCATE_DEPTH == 1)
0118             REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
0119                     FMT_TRUNCATE_EN, 1,
0120                     FMT_TRUNCATE_DEPTH, 1,
0121                     FMT_TRUNCATE_MODE, 0);
0122         else if (params->flags.TRUNCATE_DEPTH == 2)
0123             /*  10bpc trunc on YCbCr422*/
0124             REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
0125                     FMT_TRUNCATE_EN, 1,
0126                     FMT_TRUNCATE_DEPTH, 2,
0127                     FMT_TRUNCATE_MODE, 0);
0128         return;
0129     }
0130     /* on other format-to do */
0131     if (params->flags.TRUNCATE_ENABLED == 0)
0132         return;
0133     /*Set truncation depth and Enable truncation*/
0134     REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
0135                 FMT_TRUNCATE_EN, 1,
0136                 FMT_TRUNCATE_DEPTH,
0137                 params->flags.TRUNCATE_DEPTH,
0138                 FMT_TRUNCATE_MODE,
0139                 params->flags.TRUNCATE_MODE);
0140 }
0141 
0142 #if defined(CONFIG_DRM_AMD_DC_SI)
0143 /*
0144  *  dce60_set_truncation
0145  *  1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
0146  *  2) enable truncation
0147  *  3) HW remove 12bit FMT support for DCE11 power saving reason.
0148  */
0149 static void dce60_set_truncation(
0150         struct dce110_opp *opp110,
0151         const struct bit_depth_reduction_params *params)
0152 {
0153     /* DCE6 has no FMT_TRUNCATE_MODE bit in FMT_BIT_DEPTH_CONTROL reg */
0154 
0155     /*Disable truncation*/
0156     REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
0157             FMT_TRUNCATE_EN, 0,
0158             FMT_TRUNCATE_DEPTH, 0);
0159 
0160     if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
0161         /*  8bpc trunc on YCbCr422*/
0162         if (params->flags.TRUNCATE_DEPTH == 1)
0163             REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
0164                     FMT_TRUNCATE_EN, 1,
0165                     FMT_TRUNCATE_DEPTH, 1);
0166         else if (params->flags.TRUNCATE_DEPTH == 2)
0167             /*  10bpc trunc on YCbCr422*/
0168             REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
0169                     FMT_TRUNCATE_EN, 1,
0170                     FMT_TRUNCATE_DEPTH, 2);
0171         return;
0172     }
0173     /* on other format-to do */
0174     if (params->flags.TRUNCATE_ENABLED == 0)
0175         return;
0176     /*Set truncation depth and Enable truncation*/
0177     REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
0178                 FMT_TRUNCATE_EN, 1,
0179                 FMT_TRUNCATE_DEPTH,
0180                 params->flags.TRUNCATE_DEPTH);
0181 }
0182 #endif
0183 
0184 /*
0185  *  set_spatial_dither
0186  *  1) set spatial dithering mode: pattern of seed
0187  *  2) set spatial dithering depth: 0 for 18bpp or 1 for 24bpp
0188  *  3) set random seed
0189  *  4) set random mode
0190  *      lfsr is reset every frame or not reset
0191  *      RGB dithering method
0192  *      0: RGB data are all dithered with x^28+x^3+1
0193  *      1: R data is dithered with x^28+x^3+1
0194  *      G data is dithered with x^28+X^9+1
0195  *      B data is dithered with x^28+x^13+1
0196  *      enable high pass filter or not
0197  *  5) enable spatical dithering
0198  */
0199 static void set_spatial_dither(
0200     struct dce110_opp *opp110,
0201     const struct bit_depth_reduction_params *params)
0202 {
0203     /*Disable spatial (random) dithering*/
0204     REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
0205         FMT_SPATIAL_DITHER_EN, 0,
0206         FMT_SPATIAL_DITHER_DEPTH, 0,
0207         FMT_SPATIAL_DITHER_MODE, 0);
0208 
0209     REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
0210         FMT_HIGHPASS_RANDOM_ENABLE, 0,
0211         FMT_FRAME_RANDOM_ENABLE, 0,
0212         FMT_RGB_RANDOM_ENABLE, 0);
0213 
0214     REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
0215         FMT_TEMPORAL_DITHER_EN, 0);
0216 
0217     if (params->flags.SPATIAL_DITHER_ENABLED == 0)
0218         return;
0219 
0220     /* only use FRAME_COUNTER_MAX if frameRandom == 1*/
0221 
0222     if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX &&
0223             opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) {
0224         if (params->flags.FRAME_RANDOM == 1) {
0225             if (params->flags.SPATIAL_DITHER_DEPTH == 0 ||
0226             params->flags.SPATIAL_DITHER_DEPTH == 1) {
0227                 REG_UPDATE_2(FMT_CONTROL,
0228                     FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
0229                     FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
0230             } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
0231                 REG_UPDATE_2(FMT_CONTROL,
0232                     FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
0233                     FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
0234             } else
0235                 return;
0236         } else {
0237             REG_UPDATE_2(FMT_CONTROL,
0238                     FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
0239                     FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
0240         }
0241     }
0242     /* Set seed for random values for
0243      * spatial dithering for R,G,B channels
0244      */
0245     REG_UPDATE(FMT_DITHER_RAND_R_SEED,
0246             FMT_RAND_R_SEED, params->r_seed_value);
0247 
0248     REG_UPDATE(FMT_DITHER_RAND_G_SEED,
0249             FMT_RAND_G_SEED, params->g_seed_value);
0250 
0251     REG_UPDATE(FMT_DITHER_RAND_B_SEED,
0252             FMT_RAND_B_SEED, params->b_seed_value);
0253 
0254     /* FMT_OFFSET_R_Cr  31:16 0x0 Setting the zero
0255      * offset for the R/Cr channel, lower 4LSB
0256      * is forced to zeros. Typically set to 0
0257      * RGB and 0x80000 YCbCr.
0258      */
0259     /* FMT_OFFSET_G_Y   31:16 0x0 Setting the zero
0260      * offset for the G/Y  channel, lower 4LSB is
0261      * forced to zeros. Typically set to 0 RGB
0262      * and 0x80000 YCbCr.
0263      */
0264     /* FMT_OFFSET_B_Cb  31:16 0x0 Setting the zero
0265      * offset for the B/Cb channel, lower 4LSB is
0266      * forced to zeros. Typically set to 0 RGB and
0267      * 0x80000 YCbCr.
0268      */
0269 
0270     /* Disable High pass filter
0271      * Reset only at startup
0272      * Set RGB data dithered with x^28+x^3+1
0273      */
0274     REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
0275         FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
0276         FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
0277         FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
0278 
0279     /* Set spatial dithering bit depth
0280      * Set spatial dithering mode
0281      * (default is Seed patterrn AAAA...)
0282      * Enable spatial dithering
0283      */
0284     REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
0285         FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
0286         FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
0287         FMT_SPATIAL_DITHER_EN, 1);
0288 }
0289 
0290 /*
0291  *  SetTemporalDither (Frame Modulation)
0292  *  1) set temporal dither depth
0293  *  2) select pattern: from hard-coded pattern or programmable pattern
0294  *  3) select optimized strips for BGR or RGB LCD sub-pixel
0295  *  4) set s matrix
0296  *  5) set t matrix
0297  *  6) set grey level for 0.25, 0.5, 0.75
0298  *  7) enable temporal dithering
0299  */
0300 
0301 static void set_temporal_dither(
0302     struct dce110_opp *opp110,
0303     const struct bit_depth_reduction_params *params)
0304 {
0305     /*Disable temporal (frame modulation) dithering first*/
0306     REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
0307         FMT_TEMPORAL_DITHER_EN, 0,
0308         FMT_TEMPORAL_DITHER_RESET, 0,
0309         FMT_TEMPORAL_DITHER_OFFSET, 0);
0310 
0311     REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
0312         FMT_TEMPORAL_DITHER_DEPTH, 0,
0313         FMT_TEMPORAL_LEVEL, 0);
0314 
0315     REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
0316         FMT_25FRC_SEL, 0,
0317         FMT_50FRC_SEL, 0,
0318         FMT_75FRC_SEL, 0);
0319 
0320     /* no 10bpc dither on DCE11*/
0321     if (params->flags.FRAME_MODULATION_ENABLED == 0 ||
0322         params->flags.FRAME_MODULATION_DEPTH == 2)
0323         return;
0324 
0325     /* Set temporal dithering depth*/
0326     REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
0327         FMT_TEMPORAL_DITHER_DEPTH, params->flags.FRAME_MODULATION_DEPTH,
0328         FMT_TEMPORAL_DITHER_RESET, 0,
0329         FMT_TEMPORAL_DITHER_OFFSET, 0);
0330 
0331     /*Select legacy pattern based on FRC and Temporal level*/
0332     if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) {
0333         REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0);
0334         /*Set s matrix*/
0335         REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0);
0336         /*Set t matrix*/
0337         REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, 0);
0338     }
0339 
0340     /*Select patterns for 0.25, 0.5 and 0.75 grey level*/
0341     REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
0342         FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL);
0343 
0344     REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
0345         FMT_25FRC_SEL, params->flags.FRC25,
0346         FMT_50FRC_SEL, params->flags.FRC50,
0347         FMT_75FRC_SEL, params->flags.FRC75);
0348 
0349     /*Enable bit reduction by temporal (frame modulation) dithering*/
0350     REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
0351         FMT_TEMPORAL_DITHER_EN, 1);
0352 }
0353 
0354 /*
0355  *  Set Clamping
0356  *  1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
0357  *      1 for 8 bpc
0358  *      2 for 10 bpc
0359  *      3 for 12 bpc
0360  *      7 for programable
0361  *  2) Enable clamp if Limited range requested
0362  */
0363 void dce110_opp_set_clamping(
0364     struct dce110_opp *opp110,
0365     const struct clamping_and_pixel_encoding_params *params)
0366 {
0367     REG_SET_2(FMT_CLAMP_CNTL, 0,
0368         FMT_CLAMP_DATA_EN, 0,
0369         FMT_CLAMP_COLOR_FORMAT, 0);
0370 
0371     switch (params->clamping_level) {
0372     case CLAMPING_FULL_RANGE:
0373         break;
0374     case CLAMPING_LIMITED_RANGE_8BPC:
0375         REG_SET_2(FMT_CLAMP_CNTL, 0,
0376             FMT_CLAMP_DATA_EN, 1,
0377             FMT_CLAMP_COLOR_FORMAT, 1);
0378         break;
0379     case CLAMPING_LIMITED_RANGE_10BPC:
0380         REG_SET_2(FMT_CLAMP_CNTL, 0,
0381             FMT_CLAMP_DATA_EN, 1,
0382             FMT_CLAMP_COLOR_FORMAT, 2);
0383         break;
0384     case CLAMPING_LIMITED_RANGE_12BPC:
0385         REG_SET_2(FMT_CLAMP_CNTL, 0,
0386             FMT_CLAMP_DATA_EN, 1,
0387             FMT_CLAMP_COLOR_FORMAT, 3);
0388         break;
0389     case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
0390         /*Set clamp control*/
0391         REG_SET_2(FMT_CLAMP_CNTL, 0,
0392             FMT_CLAMP_DATA_EN, 1,
0393             FMT_CLAMP_COLOR_FORMAT, 7);
0394 
0395         /*set the defaults*/
0396         REG_SET_2(FMT_CLAMP_COMPONENT_R, 0,
0397             FMT_CLAMP_LOWER_R, 0x10,
0398             FMT_CLAMP_UPPER_R, 0xFEF);
0399 
0400         REG_SET_2(FMT_CLAMP_COMPONENT_G, 0,
0401             FMT_CLAMP_LOWER_G, 0x10,
0402             FMT_CLAMP_UPPER_G, 0xFEF);
0403 
0404         REG_SET_2(FMT_CLAMP_COMPONENT_B, 0,
0405             FMT_CLAMP_LOWER_B, 0x10,
0406             FMT_CLAMP_UPPER_B, 0xFEF);
0407         break;
0408     default:
0409         break;
0410     }
0411 }
0412 
0413 #if defined(CONFIG_DRM_AMD_DC_SI)
0414 /*
0415  *  Set Clamping for DCE6 parts
0416  *  1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
0417  *      1 for 8 bpc
0418  *      2 for 10 bpc
0419  *      3 for 12 bpc
0420  *      7 for programable
0421  *  2) Enable clamp if Limited range requested
0422  */
0423 static void dce60_opp_set_clamping(
0424     struct dce110_opp *opp110,
0425     const struct clamping_and_pixel_encoding_params *params)
0426 {
0427     REG_SET_2(FMT_CLAMP_CNTL, 0,
0428         FMT_CLAMP_DATA_EN, 0,
0429         FMT_CLAMP_COLOR_FORMAT, 0);
0430 
0431     switch (params->clamping_level) {
0432     case CLAMPING_FULL_RANGE:
0433         break;
0434     case CLAMPING_LIMITED_RANGE_8BPC:
0435         REG_SET_2(FMT_CLAMP_CNTL, 0,
0436             FMT_CLAMP_DATA_EN, 1,
0437             FMT_CLAMP_COLOR_FORMAT, 1);
0438         break;
0439     case CLAMPING_LIMITED_RANGE_10BPC:
0440         REG_SET_2(FMT_CLAMP_CNTL, 0,
0441             FMT_CLAMP_DATA_EN, 1,
0442             FMT_CLAMP_COLOR_FORMAT, 2);
0443         break;
0444     case CLAMPING_LIMITED_RANGE_12BPC:
0445         REG_SET_2(FMT_CLAMP_CNTL, 0,
0446             FMT_CLAMP_DATA_EN, 1,
0447             FMT_CLAMP_COLOR_FORMAT, 3);
0448         break;
0449     case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
0450         /*Set clamp control*/
0451         REG_SET_2(FMT_CLAMP_CNTL, 0,
0452             FMT_CLAMP_DATA_EN, 1,
0453             FMT_CLAMP_COLOR_FORMAT, 7);
0454 
0455         /* DCE6 does have FMT_CLAMP_COMPONENT_{R,G,B} registers */
0456 
0457         break;
0458     default:
0459         break;
0460     }
0461 }
0462 #endif
0463 
0464 /*
0465  *  set_pixel_encoding
0466  *
0467  *  Set Pixel Encoding
0468  *      0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
0469  *      1: YCbCr 4:2:2
0470  */
0471 static void set_pixel_encoding(
0472     struct dce110_opp *opp110,
0473     const struct clamping_and_pixel_encoding_params *params)
0474 {
0475     if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS)
0476         REG_UPDATE_3(FMT_CONTROL,
0477                 FMT_PIXEL_ENCODING, 0,
0478                 FMT_SUBSAMPLING_MODE, 0,
0479                 FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
0480     else
0481         REG_UPDATE_2(FMT_CONTROL,
0482                 FMT_PIXEL_ENCODING, 0,
0483                 FMT_SUBSAMPLING_MODE, 0);
0484 
0485     if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
0486         REG_UPDATE_2(FMT_CONTROL,
0487                 FMT_PIXEL_ENCODING, 1,
0488                 FMT_SUBSAMPLING_ORDER, 0);
0489     }
0490     if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
0491         REG_UPDATE_3(FMT_CONTROL,
0492                 FMT_PIXEL_ENCODING, 2,
0493                 FMT_SUBSAMPLING_MODE, 2,
0494                 FMT_CBCR_BIT_REDUCTION_BYPASS, 1);
0495     }
0496 
0497 }
0498 
0499 #if defined(CONFIG_DRM_AMD_DC_SI)
0500 /*
0501  *  dce60_set_pixel_encoding
0502  *  DCE6 has no FMT_SUBSAMPLING_{MODE,ORDER} bits in FMT_CONTROL reg
0503  *  Set Pixel Encoding
0504  *      0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
0505  *      1: YCbCr 4:2:2
0506  */
0507 static void dce60_set_pixel_encoding(
0508     struct dce110_opp *opp110,
0509     const struct clamping_and_pixel_encoding_params *params)
0510 {
0511     if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS)
0512         REG_UPDATE_2(FMT_CONTROL,
0513                 FMT_PIXEL_ENCODING, 0,
0514                 FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
0515     else
0516         REG_UPDATE(FMT_CONTROL,
0517                 FMT_PIXEL_ENCODING, 0);
0518 
0519     if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
0520         REG_UPDATE(FMT_CONTROL,
0521                 FMT_PIXEL_ENCODING, 1);
0522     }
0523     if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
0524         REG_UPDATE_2(FMT_CONTROL,
0525                 FMT_PIXEL_ENCODING, 2,
0526                 FMT_CBCR_BIT_REDUCTION_BYPASS, 1);
0527     }
0528 
0529 }
0530 #endif
0531 
0532 void dce110_opp_program_bit_depth_reduction(
0533     struct output_pixel_processor *opp,
0534     const struct bit_depth_reduction_params *params)
0535 {
0536     struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
0537 
0538     set_truncation(opp110, params);
0539     set_spatial_dither(opp110, params);
0540     set_temporal_dither(opp110, params);
0541 }
0542 
0543 #if defined(CONFIG_DRM_AMD_DC_SI)
0544 static void dce60_opp_program_bit_depth_reduction(
0545     struct output_pixel_processor *opp,
0546     const struct bit_depth_reduction_params *params)
0547 {
0548     struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
0549 
0550     dce60_set_truncation(opp110, params);
0551     set_spatial_dither(opp110, params);
0552     set_temporal_dither(opp110, params);
0553 }
0554 #endif
0555 
0556 void dce110_opp_program_clamping_and_pixel_encoding(
0557     struct output_pixel_processor *opp,
0558     const struct clamping_and_pixel_encoding_params *params)
0559 {
0560     struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
0561 
0562     dce110_opp_set_clamping(opp110, params);
0563     set_pixel_encoding(opp110, params);
0564 }
0565 
0566 #if defined(CONFIG_DRM_AMD_DC_SI)
0567 static void dce60_opp_program_clamping_and_pixel_encoding(
0568     struct output_pixel_processor *opp,
0569     const struct clamping_and_pixel_encoding_params *params)
0570 {
0571     struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
0572 
0573     dce60_opp_set_clamping(opp110, params);
0574     dce60_set_pixel_encoding(opp110, params);
0575 }
0576 #endif
0577 
0578 
0579 static void program_formatter_420_memory(struct output_pixel_processor *opp)
0580 {
0581     struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
0582     uint32_t fmt_mem_cntl_value;
0583 
0584     /* Program source select*/
0585     /* Use HW default source select for FMT_MEMORYx_CONTROL */
0586     /* Use that value for FMT_SRC_SELECT as well*/
0587     REG_GET(CONTROL,
0588             FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value);
0589 
0590     REG_UPDATE(FMT_CONTROL,
0591             FMT_SRC_SELECT, fmt_mem_cntl_value);
0592 
0593     /* Turn on the memory */
0594     REG_UPDATE(CONTROL,
0595             FMT420_MEM0_PWR_FORCE, 0);
0596 }
0597 
0598 void dce110_opp_set_dyn_expansion(
0599     struct output_pixel_processor *opp,
0600     enum dc_color_space color_sp,
0601     enum dc_color_depth color_dpth,
0602     enum signal_type signal)
0603 {
0604     struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
0605 
0606     REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
0607             FMT_DYNAMIC_EXP_EN, 0,
0608             FMT_DYNAMIC_EXP_MODE, 0);
0609 
0610     /*00 - 10-bit -> 12-bit dynamic expansion*/
0611     /*01 - 8-bit  -> 12-bit dynamic expansion*/
0612     if (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
0613         signal == SIGNAL_TYPE_DISPLAY_PORT ||
0614         signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
0615         switch (color_dpth) {
0616         case COLOR_DEPTH_888:
0617             REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
0618                 FMT_DYNAMIC_EXP_EN, 1,
0619                 FMT_DYNAMIC_EXP_MODE, 1);
0620             break;
0621         case COLOR_DEPTH_101010:
0622             REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
0623                 FMT_DYNAMIC_EXP_EN, 1,
0624                 FMT_DYNAMIC_EXP_MODE, 0);
0625             break;
0626         case COLOR_DEPTH_121212:
0627             REG_UPDATE_2(
0628                 FMT_DYNAMIC_EXP_CNTL,
0629                 FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/
0630                 FMT_DYNAMIC_EXP_MODE, 0);
0631             break;
0632         default:
0633             break;
0634         }
0635     }
0636 }
0637 
0638 static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp)
0639 {
0640     struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
0641 
0642     /* clear previous phase lock status*/
0643     REG_UPDATE(FMT_CONTROL,
0644             FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1);
0645 
0646     /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/
0647     REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10);
0648 
0649 }
0650 
0651 void dce110_opp_program_fmt(
0652     struct output_pixel_processor *opp,
0653     struct bit_depth_reduction_params *fmt_bit_depth,
0654     struct clamping_and_pixel_encoding_params *clamping)
0655 {
0656     /* dithering is affected by <CrtcSourceSelect>, hence should be
0657      * programmed afterwards */
0658 
0659     if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
0660         program_formatter_420_memory(opp);
0661 
0662     dce110_opp_program_bit_depth_reduction(
0663         opp,
0664         fmt_bit_depth);
0665 
0666     dce110_opp_program_clamping_and_pixel_encoding(
0667         opp,
0668         clamping);
0669 
0670     if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
0671         program_formatter_reset_dig_resync_fifo(opp);
0672 
0673     return;
0674 }
0675 
0676 #if defined(CONFIG_DRM_AMD_DC_SI)
0677 static void dce60_opp_program_fmt(
0678     struct output_pixel_processor *opp,
0679     struct bit_depth_reduction_params *fmt_bit_depth,
0680     struct clamping_and_pixel_encoding_params *clamping)
0681 {
0682     /* dithering is affected by <CrtcSourceSelect>, hence should be
0683      * programmed afterwards */
0684 
0685     if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
0686         program_formatter_420_memory(opp);
0687 
0688     dce60_opp_program_bit_depth_reduction(
0689         opp,
0690         fmt_bit_depth);
0691 
0692     dce60_opp_program_clamping_and_pixel_encoding(
0693         opp,
0694         clamping);
0695 
0696     if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
0697         program_formatter_reset_dig_resync_fifo(opp);
0698 
0699     return;
0700 }
0701 #endif
0702 
0703 
0704 
0705 /*****************************************/
0706 /* Constructor, Destructor               */
0707 /*****************************************/
0708 
0709 static const struct opp_funcs funcs = {
0710     .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
0711     .opp_destroy = dce110_opp_destroy,
0712     .opp_program_fmt = dce110_opp_program_fmt,
0713     .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction
0714 };
0715 
0716 #if defined(CONFIG_DRM_AMD_DC_SI)
0717 static const struct opp_funcs dce60_opp_funcs = {
0718     .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
0719     .opp_destroy = dce110_opp_destroy,
0720     .opp_program_fmt = dce60_opp_program_fmt,
0721     .opp_program_bit_depth_reduction = dce60_opp_program_bit_depth_reduction
0722 };
0723 #endif
0724 
0725 void dce110_opp_construct(struct dce110_opp *opp110,
0726     struct dc_context *ctx,
0727     uint32_t inst,
0728     const struct dce_opp_registers *regs,
0729     const struct dce_opp_shift *opp_shift,
0730     const struct dce_opp_mask *opp_mask)
0731 {
0732     opp110->base.funcs = &funcs;
0733 
0734     opp110->base.ctx = ctx;
0735 
0736     opp110->base.inst = inst;
0737 
0738     opp110->regs = regs;
0739     opp110->opp_shift = opp_shift;
0740     opp110->opp_mask = opp_mask;
0741 }
0742 
0743 #if defined(CONFIG_DRM_AMD_DC_SI)
0744 void dce60_opp_construct(struct dce110_opp *opp110,
0745     struct dc_context *ctx,
0746     uint32_t inst,
0747     const struct dce_opp_registers *regs,
0748     const struct dce_opp_shift *opp_shift,
0749     const struct dce_opp_mask *opp_mask)
0750 {
0751     opp110->base.funcs = &dce60_opp_funcs;
0752 
0753     opp110->base.ctx = ctx;
0754 
0755     opp110->base.inst = inst;
0756 
0757     opp110->regs = regs;
0758     opp110->opp_shift = opp_shift;
0759     opp110->opp_mask = opp_mask;
0760 }
0761 #endif
0762 
0763 void dce110_opp_destroy(struct output_pixel_processor **opp)
0764 {
0765     if (*opp)
0766         kfree(FROM_DCE11_OPP(*opp));
0767     *opp = NULL;
0768 }
0769