0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "dm_services.h"
0027 #include "dcn10_opp.h"
0028 #include "reg_helper.h"
0029
0030 #define REG(reg) \
0031 (oppn10->regs->reg)
0032
0033 #undef FN
0034 #define FN(reg_name, field_name) \
0035 oppn10->opp_shift->field_name, oppn10->opp_mask->field_name
0036
0037 #define CTX \
0038 oppn10->base.ctx
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049 static void opp1_set_truncation(
0050 struct dcn10_opp *oppn10,
0051 const struct bit_depth_reduction_params *params)
0052 {
0053 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
0054 FMT_TRUNCATE_EN, params->flags.TRUNCATE_ENABLED,
0055 FMT_TRUNCATE_DEPTH, params->flags.TRUNCATE_DEPTH,
0056 FMT_TRUNCATE_MODE, params->flags.TRUNCATE_MODE);
0057 }
0058
0059 static void opp1_set_spatial_dither(
0060 struct dcn10_opp *oppn10,
0061 const struct bit_depth_reduction_params *params)
0062 {
0063
0064 REG_UPDATE_7(FMT_BIT_DEPTH_CONTROL,
0065 FMT_SPATIAL_DITHER_EN, 0,
0066 FMT_SPATIAL_DITHER_MODE, 0,
0067 FMT_SPATIAL_DITHER_DEPTH, 0,
0068 FMT_TEMPORAL_DITHER_EN, 0,
0069 FMT_HIGHPASS_RANDOM_ENABLE, 0,
0070 FMT_FRAME_RANDOM_ENABLE, 0,
0071 FMT_RGB_RANDOM_ENABLE, 0);
0072
0073
0074
0075 if (params->flags.FRAME_RANDOM == 1) {
0076 if (params->flags.SPATIAL_DITHER_DEPTH == 0 || params->flags.SPATIAL_DITHER_DEPTH == 1) {
0077 REG_UPDATE_2(FMT_CONTROL,
0078 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
0079 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
0080 } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
0081 REG_UPDATE_2(FMT_CONTROL,
0082 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
0083 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
0084 } else {
0085 return;
0086 }
0087 } else {
0088 REG_UPDATE_2(FMT_CONTROL,
0089 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
0090 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
0091 }
0092
0093
0094
0095
0096 REG_SET(FMT_DITHER_RAND_R_SEED, 0,
0097 FMT_RAND_R_SEED, params->r_seed_value);
0098
0099 REG_SET(FMT_DITHER_RAND_G_SEED, 0,
0100 FMT_RAND_G_SEED, params->g_seed_value);
0101
0102 REG_SET(FMT_DITHER_RAND_B_SEED, 0,
0103 FMT_RAND_B_SEED, params->b_seed_value);
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121 REG_UPDATE_6(FMT_BIT_DEPTH_CONTROL,
0122
0123 FMT_SPATIAL_DITHER_EN, params->flags.SPATIAL_DITHER_ENABLED,
0124
0125
0126
0127 FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
0128
0129 FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
0130
0131 FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
0132
0133 FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
0134
0135 FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
0136 }
0137
0138 void opp1_program_bit_depth_reduction(
0139 struct output_pixel_processor *opp,
0140 const struct bit_depth_reduction_params *params)
0141 {
0142 struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
0143
0144 opp1_set_truncation(oppn10, params);
0145 opp1_set_spatial_dither(oppn10, params);
0146
0147
0148
0149 }
0150
0151
0152
0153
0154
0155
0156
0157
0158 static void opp1_set_pixel_encoding(
0159 struct dcn10_opp *oppn10,
0160 const struct clamping_and_pixel_encoding_params *params)
0161 {
0162 switch (params->pixel_encoding) {
0163
0164 case PIXEL_ENCODING_RGB:
0165 case PIXEL_ENCODING_YCBCR444:
0166 REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 0);
0167 break;
0168 case PIXEL_ENCODING_YCBCR422:
0169 REG_UPDATE_3(FMT_CONTROL,
0170 FMT_PIXEL_ENCODING, 1,
0171 FMT_SUBSAMPLING_MODE, 2,
0172 FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
0173 break;
0174 case PIXEL_ENCODING_YCBCR420:
0175 REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 2);
0176 break;
0177 default:
0178 break;
0179 }
0180 }
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 static void opp1_set_clamping(
0192 struct dcn10_opp *oppn10,
0193 const struct clamping_and_pixel_encoding_params *params)
0194 {
0195 REG_UPDATE_2(FMT_CLAMP_CNTL,
0196 FMT_CLAMP_DATA_EN, 0,
0197 FMT_CLAMP_COLOR_FORMAT, 0);
0198
0199 switch (params->clamping_level) {
0200 case CLAMPING_FULL_RANGE:
0201 REG_UPDATE_2(FMT_CLAMP_CNTL,
0202 FMT_CLAMP_DATA_EN, 1,
0203 FMT_CLAMP_COLOR_FORMAT, 0);
0204 break;
0205 case CLAMPING_LIMITED_RANGE_8BPC:
0206 REG_UPDATE_2(FMT_CLAMP_CNTL,
0207 FMT_CLAMP_DATA_EN, 1,
0208 FMT_CLAMP_COLOR_FORMAT, 1);
0209 break;
0210 case CLAMPING_LIMITED_RANGE_10BPC:
0211 REG_UPDATE_2(FMT_CLAMP_CNTL,
0212 FMT_CLAMP_DATA_EN, 1,
0213 FMT_CLAMP_COLOR_FORMAT, 2);
0214
0215 break;
0216 case CLAMPING_LIMITED_RANGE_12BPC:
0217 REG_UPDATE_2(FMT_CLAMP_CNTL,
0218 FMT_CLAMP_DATA_EN, 1,
0219 FMT_CLAMP_COLOR_FORMAT, 3);
0220 break;
0221 case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
0222
0223 default:
0224 break;
0225 }
0226
0227 }
0228
0229 void opp1_set_dyn_expansion(
0230 struct output_pixel_processor *opp,
0231 enum dc_color_space color_sp,
0232 enum dc_color_depth color_dpth,
0233 enum signal_type signal)
0234 {
0235 struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
0236
0237 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
0238 FMT_DYNAMIC_EXP_EN, 0,
0239 FMT_DYNAMIC_EXP_MODE, 0);
0240
0241 if (opp->dyn_expansion == DYN_EXPANSION_DISABLE)
0242 return;
0243
0244
0245
0246 if (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
0247 signal == SIGNAL_TYPE_DISPLAY_PORT ||
0248 signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
0249 signal == SIGNAL_TYPE_VIRTUAL) {
0250 switch (color_dpth) {
0251 case COLOR_DEPTH_888:
0252 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
0253 FMT_DYNAMIC_EXP_EN, 1,
0254 FMT_DYNAMIC_EXP_MODE, 1);
0255 break;
0256 case COLOR_DEPTH_101010:
0257 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
0258 FMT_DYNAMIC_EXP_EN, 1,
0259 FMT_DYNAMIC_EXP_MODE, 0);
0260 break;
0261 case COLOR_DEPTH_121212:
0262 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
0263 FMT_DYNAMIC_EXP_EN, 1,
0264 FMT_DYNAMIC_EXP_MODE, 0);
0265 break;
0266 default:
0267 break;
0268 }
0269 }
0270 }
0271
0272 static void opp1_program_clamping_and_pixel_encoding(
0273 struct output_pixel_processor *opp,
0274 const struct clamping_and_pixel_encoding_params *params)
0275 {
0276 struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
0277
0278 opp1_set_clamping(oppn10, params);
0279 opp1_set_pixel_encoding(oppn10, params);
0280 }
0281
0282 void opp1_program_fmt(
0283 struct output_pixel_processor *opp,
0284 struct bit_depth_reduction_params *fmt_bit_depth,
0285 struct clamping_and_pixel_encoding_params *clamping)
0286 {
0287 struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
0288
0289 if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
0290 REG_UPDATE(FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, 0);
0291
0292
0293
0294 opp1_program_bit_depth_reduction(
0295 opp,
0296 fmt_bit_depth);
0297
0298 opp1_program_clamping_and_pixel_encoding(
0299 opp,
0300 clamping);
0301
0302 return;
0303 }
0304
0305 void opp1_program_stereo(
0306 struct output_pixel_processor *opp,
0307 bool enable,
0308 const struct dc_crtc_timing *timing)
0309 {
0310 struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
0311
0312 uint32_t active_width = timing->h_addressable - timing->h_border_right - timing->h_border_right;
0313 uint32_t space1_size = timing->v_total - timing->v_addressable;
0314
0315 uint32_t space2_size = timing->v_total - timing->v_addressable;
0316
0317 if (!enable) {
0318 active_width = 0;
0319 space1_size = 0;
0320 space2_size = 0;
0321 }
0322
0323
0324 REG_UPDATE(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, 0);
0325
0326 REG_UPDATE(OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, active_width);
0327
0328
0329
0330
0331
0332
0333 if (timing->timing_3d_format == TIMING_3D_FORMAT_FRAME_ALTERNATE)
0334 REG_UPDATE(OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE2_SIZE, space2_size);
0335 else
0336 REG_UPDATE(OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, space1_size);
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347 }
0348
0349 void opp1_pipe_clock_control(struct output_pixel_processor *opp, bool enable)
0350 {
0351 struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
0352 uint32_t regval = enable ? 1 : 0;
0353
0354 REG_UPDATE(OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, regval);
0355 }
0356
0357
0358
0359
0360
0361 void opp1_destroy(struct output_pixel_processor **opp)
0362 {
0363 kfree(TO_DCN10_OPP(*opp));
0364 *opp = NULL;
0365 }
0366
0367 static const struct opp_funcs dcn10_opp_funcs = {
0368 .opp_set_dyn_expansion = opp1_set_dyn_expansion,
0369 .opp_program_fmt = opp1_program_fmt,
0370 .opp_program_bit_depth_reduction = opp1_program_bit_depth_reduction,
0371 .opp_program_stereo = opp1_program_stereo,
0372 .opp_pipe_clock_control = opp1_pipe_clock_control,
0373 .opp_set_disp_pattern_generator = NULL,
0374 .opp_program_dpg_dimensions = NULL,
0375 .dpg_is_blanked = NULL,
0376 .opp_destroy = opp1_destroy
0377 };
0378
0379 void dcn10_opp_construct(struct dcn10_opp *oppn10,
0380 struct dc_context *ctx,
0381 uint32_t inst,
0382 const struct dcn10_opp_registers *regs,
0383 const struct dcn10_opp_shift *opp_shift,
0384 const struct dcn10_opp_mask *opp_mask)
0385 {
0386
0387 oppn10->base.ctx = ctx;
0388 oppn10->base.inst = inst;
0389 oppn10->base.funcs = &dcn10_opp_funcs;
0390
0391 oppn10->regs = regs;
0392 oppn10->opp_shift = opp_shift;
0393 oppn10->opp_mask = opp_mask;
0394 }