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
0028 #include "dce/dce_11_0_d.h"
0029 #include "dce/dce_11_0_sh_mask.h"
0030 #include "gmc/gmc_8_2_sh_mask.h"
0031 #include "gmc/gmc_8_2_d.h"
0032
0033 #include "include/logger_interface.h"
0034
0035 #include "dce110_compressor.h"
0036
0037 #define DC_LOGGER \
0038 cp110->base.ctx->logger
0039 #define DCP_REG(reg)\
0040 (reg + cp110->offsets.dcp_offset)
0041 #define DMIF_REG(reg)\
0042 (reg + cp110->offsets.dmif_offset)
0043
0044 static const struct dce110_compressor_reg_offsets reg_offsets[] = {
0045 {
0046 .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
0047 .dmif_offset =
0048 (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
0049 - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
0050 },
0051 {
0052 .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
0053 .dmif_offset =
0054 (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL
0055 - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
0056 },
0057 {
0058 .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
0059 .dmif_offset =
0060 (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL
0061 - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
0062 }
0063 };
0064
0065 static uint32_t align_to_chunks_number_per_line(uint32_t pixels)
0066 {
0067 return 256 * ((pixels + 255) / 256);
0068 }
0069
0070 static void reset_lb_on_vblank(struct compressor *compressor, uint32_t crtc_inst)
0071 {
0072 uint32_t value;
0073 uint32_t frame_count;
0074 uint32_t status_pos;
0075 uint32_t retry = 0;
0076 struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
0077
0078 cp110->offsets = reg_offsets[crtc_inst];
0079
0080 status_pos = dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_POSITION));
0081
0082
0083
0084 if (status_pos != dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_POSITION))) {
0085
0086 value = dm_read_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL));
0087 set_reg_field_value(value, 3, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL);
0088 set_reg_field_value(value, 1, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2);
0089 dm_write_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL), value);
0090
0091 frame_count = dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_FRAME_COUNT));
0092
0093
0094 for (retry = 10000; retry > 0; retry--) {
0095 if (frame_count != dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_FRAME_COUNT)))
0096 break;
0097 udelay(10);
0098 }
0099 if (!retry)
0100 dm_error("Frame count did not increase for 100ms.\n");
0101
0102
0103 value = dm_read_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL));
0104 set_reg_field_value(value, 2, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL);
0105 set_reg_field_value(value, 0, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2);
0106 dm_write_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL), value);
0107 }
0108 }
0109
0110 static void wait_for_fbc_state_changed(
0111 struct dce110_compressor *cp110,
0112 bool enabled)
0113 {
0114 uint32_t counter = 0;
0115 uint32_t addr = mmFBC_STATUS;
0116 uint32_t value;
0117
0118 while (counter < 1000) {
0119 value = dm_read_reg(cp110->base.ctx, addr);
0120 if (get_reg_field_value(
0121 value,
0122 FBC_STATUS,
0123 FBC_ENABLE_STATUS) == enabled)
0124 break;
0125 udelay(100);
0126 counter++;
0127 }
0128
0129 if (counter == 1000) {
0130 DC_LOG_WARNING("%s: wait counter exceeded, changes to HW not applied",
0131 __func__);
0132 } else {
0133 DC_LOG_SYNC("FBC status changed to %d", enabled);
0134 }
0135
0136
0137 }
0138
0139 void dce110_compressor_power_up_fbc(struct compressor *compressor)
0140 {
0141 uint32_t value;
0142 uint32_t addr;
0143
0144 addr = mmFBC_CNTL;
0145 value = dm_read_reg(compressor->ctx, addr);
0146 set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
0147 set_reg_field_value(value, 1, FBC_CNTL, FBC_EN);
0148 set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE);
0149 if (compressor->options.bits.CLK_GATING_DISABLED == 1) {
0150
0151 set_reg_field_value(
0152 value,
0153 0,
0154 FBC_CNTL,
0155 FBC_COMP_CLK_GATE_EN);
0156 }
0157 dm_write_reg(compressor->ctx, addr, value);
0158
0159 addr = mmFBC_COMP_MODE;
0160 value = dm_read_reg(compressor->ctx, addr);
0161 set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN);
0162 set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN);
0163 set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN);
0164 dm_write_reg(compressor->ctx, addr, value);
0165
0166 addr = mmFBC_COMP_CNTL;
0167 value = dm_read_reg(compressor->ctx, addr);
0168 set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN);
0169 dm_write_reg(compressor->ctx, addr, value);
0170
0171
0172
0173
0174 set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION);
0175 dm_write_reg(compressor->ctx, addr, value);
0176 compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1;
0177
0178 value = 0;
0179 dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value);
0180
0181 value = 0xFFFFFF;
0182 dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value);
0183 }
0184
0185 void dce110_compressor_enable_fbc(
0186 struct compressor *compressor,
0187 struct compr_addr_and_pitch_params *params)
0188 {
0189 struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
0190
0191 if (compressor->options.bits.FBC_SUPPORT &&
0192 (!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL))) {
0193
0194 uint32_t addr;
0195 uint32_t value, misc_value;
0196
0197 addr = mmFBC_CNTL;
0198 value = dm_read_reg(compressor->ctx, addr);
0199 set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
0200
0201 set_reg_field_value(
0202 value,
0203 params->inst,
0204 FBC_CNTL, FBC_SRC_SEL);
0205 dm_write_reg(compressor->ctx, addr, value);
0206
0207
0208 compressor->is_enabled = true;
0209
0210
0211
0212 compressor->attached_inst = params->inst + CONTROLLER_ID_D0;
0213
0214
0215 set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
0216 dm_write_reg(compressor->ctx, addr, value);
0217
0218
0219 misc_value = dm_read_reg(compressor->ctx, mmFBC_MISC);
0220
0221 set_reg_field_value(misc_value, 1,
0222 FBC_MISC, FBC_INVALIDATE_ON_ERROR);
0223 set_reg_field_value(misc_value, 1,
0224 FBC_MISC, FBC_DECOMPRESS_ERROR_CLEAR);
0225 set_reg_field_value(misc_value, 0x14,
0226 FBC_MISC, FBC_SLOW_REQ_INTERVAL);
0227
0228 dm_write_reg(compressor->ctx, mmFBC_MISC, misc_value);
0229
0230
0231 set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
0232 dm_write_reg(compressor->ctx, addr, value);
0233
0234 wait_for_fbc_state_changed(cp110, true);
0235 }
0236 }
0237
0238 void dce110_compressor_disable_fbc(struct compressor *compressor)
0239 {
0240 struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
0241 uint32_t crtc_inst = 0;
0242
0243 if (compressor->options.bits.FBC_SUPPORT) {
0244 if (dce110_compressor_is_fbc_enabled_in_hw(compressor, &crtc_inst)) {
0245 uint32_t reg_data;
0246
0247 reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL);
0248 set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
0249 dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data);
0250
0251
0252 compressor->attached_inst = 0;
0253 compressor->is_enabled = false;
0254
0255 wait_for_fbc_state_changed(cp110, false);
0256 }
0257
0258
0259 if (crtc_inst > CONTROLLER_ID_UNDEFINED && crtc_inst < CONTROLLER_ID_D3)
0260 reset_lb_on_vblank(compressor,
0261 crtc_inst - CONTROLLER_ID_D0);
0262 }
0263 }
0264
0265 bool dce110_compressor_is_fbc_enabled_in_hw(
0266 struct compressor *compressor,
0267 uint32_t *inst)
0268 {
0269
0270 uint32_t value;
0271
0272 value = dm_read_reg(compressor->ctx, mmFBC_STATUS);
0273 if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) {
0274 if (inst != NULL)
0275 *inst = compressor->attached_inst;
0276 return true;
0277 }
0278
0279 value = dm_read_reg(compressor->ctx, mmFBC_MISC);
0280 if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) {
0281 value = dm_read_reg(compressor->ctx, mmFBC_CNTL);
0282
0283 if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) {
0284 if (inst != NULL)
0285 *inst =
0286 compressor->attached_inst;
0287 return true;
0288 }
0289 }
0290 return false;
0291 }
0292
0293
0294 void dce110_compressor_program_compressed_surface_address_and_pitch(
0295 struct compressor *compressor,
0296 struct compr_addr_and_pitch_params *params)
0297 {
0298 struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
0299 uint32_t value = 0;
0300 uint32_t fbc_pitch = 0;
0301 uint32_t compressed_surf_address_low_part =
0302 compressor->compr_surface_address.addr.low_part;
0303
0304 cp110->offsets = reg_offsets[params->inst];
0305
0306
0307 dm_write_reg(
0308 compressor->ctx,
0309 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
0310 0);
0311 dm_write_reg(compressor->ctx,
0312 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0);
0313
0314
0315 dm_write_reg(compressor->ctx,
0316 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
0317 compressor->compr_surface_address.addr.high_part);
0318 dm_write_reg(compressor->ctx,
0319 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS),
0320 compressed_surf_address_low_part);
0321
0322 fbc_pitch = align_to_chunks_number_per_line(params->source_view_width);
0323
0324 if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1)
0325 fbc_pitch = fbc_pitch / 8;
0326 else
0327 DC_LOG_WARNING("%s: Unexpected DCE11 compression ratio",
0328 __func__);
0329
0330
0331 dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0);
0332
0333
0334 set_reg_field_value(
0335 value,
0336 fbc_pitch,
0337 GRPH_COMPRESS_PITCH,
0338 GRPH_COMPRESS_PITCH);
0339 dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value);
0340
0341 }
0342
0343 void dce110_compressor_set_fbc_invalidation_triggers(
0344 struct compressor *compressor,
0345 uint32_t fbc_trigger)
0346 {
0347
0348
0349
0350 uint32_t addr = mmFBC_CLIENT_REGION_MASK;
0351 uint32_t value = dm_read_reg(compressor->ctx, addr);
0352
0353 set_reg_field_value(
0354 value,
0355 0,
0356 FBC_CLIENT_REGION_MASK,
0357 FBC_MEMORY_REGION_MASK);
0358 dm_write_reg(compressor->ctx, addr, value);
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384 addr = mmFBC_IDLE_FORCE_CLEAR_MASK;
0385 value = dm_read_reg(compressor->ctx, addr);
0386 set_reg_field_value(
0387 value,
0388 fbc_trigger,
0389 FBC_IDLE_FORCE_CLEAR_MASK,
0390 FBC_IDLE_FORCE_CLEAR_MASK);
0391 dm_write_reg(compressor->ctx, addr, value);
0392 }
0393
0394 struct compressor *dce110_compressor_create(struct dc_context *ctx)
0395 {
0396 struct dce110_compressor *cp110 =
0397 kzalloc(sizeof(struct dce110_compressor), GFP_KERNEL);
0398
0399 if (!cp110)
0400 return NULL;
0401
0402 dce110_compressor_construct(cp110, ctx);
0403 return &cp110->base;
0404 }
0405
0406 void dce110_compressor_destroy(struct compressor **compressor)
0407 {
0408 kfree(TO_DCE110_COMPRESSOR(*compressor));
0409 *compressor = NULL;
0410 }
0411
0412 void get_max_support_fbc_buffersize(unsigned int *max_x, unsigned int *max_y)
0413 {
0414 *max_x = FBC_MAX_X;
0415 *max_y = FBC_MAX_Y;
0416
0417
0418
0419
0420
0421
0422
0423 }
0424
0425 static const struct compressor_funcs dce110_compressor_funcs = {
0426 .power_up_fbc = dce110_compressor_power_up_fbc,
0427 .enable_fbc = dce110_compressor_enable_fbc,
0428 .disable_fbc = dce110_compressor_disable_fbc,
0429 .set_fbc_invalidation_triggers = dce110_compressor_set_fbc_invalidation_triggers,
0430 .surface_address_and_pitch = dce110_compressor_program_compressed_surface_address_and_pitch,
0431 .is_fbc_enabled_in_hw = dce110_compressor_is_fbc_enabled_in_hw
0432 };
0433
0434
0435 void dce110_compressor_construct(struct dce110_compressor *compressor,
0436 struct dc_context *ctx)
0437 {
0438
0439 compressor->base.options.raw = 0;
0440 compressor->base.options.bits.FBC_SUPPORT = true;
0441
0442
0443 compressor->base.lpt_channels_num = 1;
0444 compressor->base.options.bits.DUMMY_BACKEND = false;
0445
0446
0447
0448
0449
0450
0451
0452 compressor->base.options.bits.CLK_GATING_DISABLED = false;
0453
0454 compressor->base.ctx = ctx;
0455 compressor->base.embedded_panel_h_size = 0;
0456 compressor->base.embedded_panel_v_size = 0;
0457 compressor->base.memory_bus_width = ctx->asic_id.vram_width;
0458 compressor->base.allocated_size = 0;
0459 compressor->base.preferred_requested_size = 0;
0460 compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID;
0461 compressor->base.banks_num = 0;
0462 compressor->base.raw_size = 0;
0463 compressor->base.channel_interleave_size = 0;
0464 compressor->base.dram_channels_num = 0;
0465 compressor->base.lpt_channels_num = 0;
0466 compressor->base.attached_inst = CONTROLLER_ID_UNDEFINED;
0467 compressor->base.is_enabled = false;
0468 compressor->base.funcs = &dce110_compressor_funcs;
0469
0470 }
0471