| .. | .. |
|---|
| 23 | 23 | * |
|---|
| 24 | 24 | */ |
|---|
| 25 | 25 | |
|---|
| 26 | +#include <linux/delay.h> |
|---|
| 27 | +#include <linux/slab.h> |
|---|
| 28 | + |
|---|
| 26 | 29 | #include "dm_services.h" |
|---|
| 27 | 30 | |
|---|
| 28 | 31 | #include "dce/dce_11_0_d.h" |
|---|
| .. | .. |
|---|
| 62 | 65 | } |
|---|
| 63 | 66 | }; |
|---|
| 64 | 67 | |
|---|
| 65 | | -static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600; |
|---|
| 66 | | - |
|---|
| 67 | | -enum fbc_idle_force { |
|---|
| 68 | | - /* Bit 0 - Display registers updated */ |
|---|
| 69 | | - FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001, |
|---|
| 70 | | - |
|---|
| 71 | | - /* Bit 2 - FBC_GRPH_COMP_EN register updated */ |
|---|
| 72 | | - FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002, |
|---|
| 73 | | - /* Bit 3 - FBC_SRC_SEL register updated */ |
|---|
| 74 | | - FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004, |
|---|
| 75 | | - /* Bit 4 - FBC_MIN_COMPRESSION register updated */ |
|---|
| 76 | | - FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008, |
|---|
| 77 | | - /* Bit 5 - FBC_ALPHA_COMP_EN register updated */ |
|---|
| 78 | | - FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010, |
|---|
| 79 | | - /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */ |
|---|
| 80 | | - FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020, |
|---|
| 81 | | - /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */ |
|---|
| 82 | | - FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040, |
|---|
| 83 | | - |
|---|
| 84 | | - /* Bit 24 - Memory write to region 0 defined by MC registers. */ |
|---|
| 85 | | - FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000, |
|---|
| 86 | | - /* Bit 25 - Memory write to region 1 defined by MC registers */ |
|---|
| 87 | | - FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000, |
|---|
| 88 | | - /* Bit 26 - Memory write to region 2 defined by MC registers */ |
|---|
| 89 | | - FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000, |
|---|
| 90 | | - /* Bit 27 - Memory write to region 3 defined by MC registers. */ |
|---|
| 91 | | - FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000, |
|---|
| 92 | | - |
|---|
| 93 | | - /* Bit 28 - Memory write from any client other than MCIF */ |
|---|
| 94 | | - FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000, |
|---|
| 95 | | - /* Bit 29 - CG statics screen signal is inactive */ |
|---|
| 96 | | - FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000, |
|---|
| 97 | | -}; |
|---|
| 98 | | - |
|---|
| 99 | | - |
|---|
| 100 | 68 | static uint32_t align_to_chunks_number_per_line(uint32_t pixels) |
|---|
| 101 | 69 | { |
|---|
| 102 | 70 | return 256 * ((pixels + 255) / 256); |
|---|
| 103 | 71 | } |
|---|
| 104 | 72 | |
|---|
| 105 | | -static void reset_lb_on_vblank(struct dc_context *ctx) |
|---|
| 73 | +static void reset_lb_on_vblank(struct compressor *compressor, uint32_t crtc_inst) |
|---|
| 106 | 74 | { |
|---|
| 107 | | - uint32_t value, frame_count; |
|---|
| 75 | + uint32_t value; |
|---|
| 76 | + uint32_t frame_count; |
|---|
| 77 | + uint32_t status_pos; |
|---|
| 108 | 78 | uint32_t retry = 0; |
|---|
| 109 | | - uint32_t status_pos = |
|---|
| 110 | | - dm_read_reg(ctx, mmCRTC_STATUS_POSITION); |
|---|
| 79 | + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); |
|---|
| 80 | + |
|---|
| 81 | + cp110->offsets = reg_offsets[crtc_inst]; |
|---|
| 82 | + |
|---|
| 83 | + status_pos = dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_POSITION)); |
|---|
| 111 | 84 | |
|---|
| 112 | 85 | |
|---|
| 113 | 86 | /* Only if CRTC is enabled and counter is moving we wait for one frame. */ |
|---|
| 114 | | - if (status_pos != dm_read_reg(ctx, mmCRTC_STATUS_POSITION)) { |
|---|
| 87 | + if (status_pos != dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_POSITION))) { |
|---|
| 115 | 88 | /* Resetting LB on VBlank */ |
|---|
| 116 | | - value = dm_read_reg(ctx, mmLB_SYNC_RESET_SEL); |
|---|
| 89 | + value = dm_read_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL)); |
|---|
| 117 | 90 | set_reg_field_value(value, 3, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL); |
|---|
| 118 | 91 | set_reg_field_value(value, 1, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2); |
|---|
| 119 | | - dm_write_reg(ctx, mmLB_SYNC_RESET_SEL, value); |
|---|
| 92 | + dm_write_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL), value); |
|---|
| 120 | 93 | |
|---|
| 121 | | - frame_count = dm_read_reg(ctx, mmCRTC_STATUS_FRAME_COUNT); |
|---|
| 94 | + frame_count = dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_FRAME_COUNT)); |
|---|
| 122 | 95 | |
|---|
| 123 | 96 | |
|---|
| 124 | 97 | for (retry = 10000; retry > 0; retry--) { |
|---|
| 125 | | - if (frame_count != dm_read_reg(ctx, mmCRTC_STATUS_FRAME_COUNT)) |
|---|
| 98 | + if (frame_count != dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_FRAME_COUNT))) |
|---|
| 126 | 99 | break; |
|---|
| 127 | 100 | udelay(10); |
|---|
| 128 | 101 | } |
|---|
| .. | .. |
|---|
| 130 | 103 | dm_error("Frame count did not increase for 100ms.\n"); |
|---|
| 131 | 104 | |
|---|
| 132 | 105 | /* Resetting LB on VBlank */ |
|---|
| 133 | | - value = dm_read_reg(ctx, mmLB_SYNC_RESET_SEL); |
|---|
| 106 | + value = dm_read_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL)); |
|---|
| 134 | 107 | set_reg_field_value(value, 2, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL); |
|---|
| 135 | 108 | set_reg_field_value(value, 0, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2); |
|---|
| 136 | | - dm_write_reg(ctx, mmLB_SYNC_RESET_SEL, value); |
|---|
| 137 | | - |
|---|
| 109 | + dm_write_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL), value); |
|---|
| 138 | 110 | } |
|---|
| 139 | | - |
|---|
| 140 | 111 | } |
|---|
| 141 | 112 | |
|---|
| 142 | 113 | static void wait_for_fbc_state_changed( |
|---|
| .. | .. |
|---|
| 226 | 197 | uint32_t addr; |
|---|
| 227 | 198 | uint32_t value, misc_value; |
|---|
| 228 | 199 | |
|---|
| 229 | | - |
|---|
| 230 | 200 | addr = mmFBC_CNTL; |
|---|
| 231 | 201 | value = dm_read_reg(compressor->ctx, addr); |
|---|
| 232 | 202 | set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); |
|---|
| 203 | + /* params->inst is valid HW CRTC instance start from 0 */ |
|---|
| 233 | 204 | set_reg_field_value( |
|---|
| 234 | 205 | value, |
|---|
| 235 | 206 | params->inst, |
|---|
| .. | .. |
|---|
| 238 | 209 | |
|---|
| 239 | 210 | /* Keep track of enum controller_id FBC is attached to */ |
|---|
| 240 | 211 | compressor->is_enabled = true; |
|---|
| 241 | | - compressor->attached_inst = params->inst; |
|---|
| 242 | | - cp110->offsets = reg_offsets[params->inst]; |
|---|
| 212 | + /* attached_inst is SW CRTC instance start from 1 |
|---|
| 213 | + * 0 = CONTROLLER_ID_UNDEFINED means not attached crtc |
|---|
| 214 | + */ |
|---|
| 215 | + compressor->attached_inst = params->inst + CONTROLLER_ID_D0; |
|---|
| 243 | 216 | |
|---|
| 244 | 217 | /* Toggle it as there is bug in HW */ |
|---|
| 245 | 218 | set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); |
|---|
| .. | .. |
|---|
| 268 | 241 | void dce110_compressor_disable_fbc(struct compressor *compressor) |
|---|
| 269 | 242 | { |
|---|
| 270 | 243 | struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); |
|---|
| 244 | + uint32_t crtc_inst = 0; |
|---|
| 271 | 245 | |
|---|
| 272 | 246 | if (compressor->options.bits.FBC_SUPPORT) { |
|---|
| 273 | | - if (dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) { |
|---|
| 247 | + if (dce110_compressor_is_fbc_enabled_in_hw(compressor, &crtc_inst)) { |
|---|
| 274 | 248 | uint32_t reg_data; |
|---|
| 275 | 249 | /* Turn off compression */ |
|---|
| 276 | 250 | reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); |
|---|
| .. | .. |
|---|
| 284 | 258 | wait_for_fbc_state_changed(cp110, false); |
|---|
| 285 | 259 | } |
|---|
| 286 | 260 | |
|---|
| 287 | | - /* Sync line buffer - dce100/110 only*/ |
|---|
| 288 | | - reset_lb_on_vblank(compressor->ctx); |
|---|
| 261 | + /* Sync line buffer which fbc was attached to dce100/110 only */ |
|---|
| 262 | + if (crtc_inst > CONTROLLER_ID_UNDEFINED && crtc_inst < CONTROLLER_ID_D3) |
|---|
| 263 | + reset_lb_on_vblank(compressor, |
|---|
| 264 | + crtc_inst - CONTROLLER_ID_D0); |
|---|
| 289 | 265 | } |
|---|
| 290 | 266 | } |
|---|
| 291 | 267 | |
|---|
| .. | .. |
|---|
| 327 | 303 | uint32_t fbc_pitch = 0; |
|---|
| 328 | 304 | uint32_t compressed_surf_address_low_part = |
|---|
| 329 | 305 | compressor->compr_surface_address.addr.low_part; |
|---|
| 306 | + |
|---|
| 307 | + cp110->offsets = reg_offsets[params->inst]; |
|---|
| 330 | 308 | |
|---|
| 331 | 309 | /* Clear content first. */ |
|---|
| 332 | 310 | dm_write_reg( |
|---|
| .. | .. |
|---|
| 410 | 388 | value = dm_read_reg(compressor->ctx, addr); |
|---|
| 411 | 389 | set_reg_field_value( |
|---|
| 412 | 390 | value, |
|---|
| 413 | | - fbc_trigger | |
|---|
| 414 | | - FBC_IDLE_FORCE_GRPH_COMP_EN | |
|---|
| 415 | | - FBC_IDLE_FORCE_SRC_SEL_CHANGE | |
|---|
| 416 | | - FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE | |
|---|
| 417 | | - FBC_IDLE_FORCE_ALPHA_COMP_EN | |
|---|
| 418 | | - FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN | |
|---|
| 419 | | - FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF, |
|---|
| 391 | + fbc_trigger, |
|---|
| 420 | 392 | FBC_IDLE_FORCE_CLEAR_MASK, |
|---|
| 421 | 393 | FBC_IDLE_FORCE_CLEAR_MASK); |
|---|
| 422 | 394 | dm_write_reg(compressor->ctx, addr, value); |
|---|
| .. | .. |
|---|
| 549 | 521 | compressor->base.channel_interleave_size = 0; |
|---|
| 550 | 522 | compressor->base.dram_channels_num = 0; |
|---|
| 551 | 523 | compressor->base.lpt_channels_num = 0; |
|---|
| 552 | | - compressor->base.attached_inst = 0; |
|---|
| 524 | + compressor->base.attached_inst = CONTROLLER_ID_UNDEFINED; |
|---|
| 553 | 525 | compressor->base.is_enabled = false; |
|---|
| 554 | 526 | compressor->base.funcs = &dce110_compressor_funcs; |
|---|
| 555 | 527 | |
|---|