Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: fbc state could not reach while enable fbc

[WHY] fbc is within the data path from memory to dce. while
re-configure mc dmif, fbc should be enabled. otherwise, fbc
may not be enabled properly.

[HOW] before re-configure mc dmif, disable fbc, only after
dmif re-configuration fully done, enable fbc again.

Signed-off-by: hersen wu <hersenxs.wu@amd.com>
Reviewed-by: Roman Li <Roman.Li@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

hersen wu and committed by
Alex Deucher
65d38262 ecd0136b

+66 -83
+31 -60
drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c
··· 64 64 65 65 static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600; 66 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 67 static uint32_t align_to_chunks_number_per_line(uint32_t pixels) 101 68 { 102 69 return 256 * ((pixels + 255) / 256); 103 70 } 104 71 105 - static void reset_lb_on_vblank(struct dc_context *ctx) 72 + static void reset_lb_on_vblank(struct compressor *compressor, uint32_t crtc_inst) 106 73 { 107 - uint32_t value, frame_count; 74 + uint32_t value; 75 + uint32_t frame_count; 76 + uint32_t status_pos; 108 77 uint32_t retry = 0; 109 - uint32_t status_pos = 110 - dm_read_reg(ctx, mmCRTC_STATUS_POSITION); 78 + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); 79 + 80 + cp110->offsets = reg_offsets[crtc_inst]; 81 + 82 + status_pos = dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_POSITION)); 111 83 112 84 113 85 /* 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)) { 86 + if (status_pos != dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_POSITION))) { 115 87 /* Resetting LB on VBlank */ 116 - value = dm_read_reg(ctx, mmLB_SYNC_RESET_SEL); 88 + value = dm_read_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL)); 117 89 set_reg_field_value(value, 3, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL); 118 90 set_reg_field_value(value, 1, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2); 119 - dm_write_reg(ctx, mmLB_SYNC_RESET_SEL, value); 91 + dm_write_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL), value); 120 92 121 - frame_count = dm_read_reg(ctx, mmCRTC_STATUS_FRAME_COUNT); 93 + frame_count = dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_FRAME_COUNT)); 122 94 123 95 124 96 for (retry = 10000; retry > 0; retry--) { 125 - if (frame_count != dm_read_reg(ctx, mmCRTC_STATUS_FRAME_COUNT)) 97 + if (frame_count != dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_FRAME_COUNT))) 126 98 break; 127 99 udelay(10); 128 100 } ··· 102 130 dm_error("Frame count did not increase for 100ms.\n"); 103 131 104 132 /* Resetting LB on VBlank */ 105 - value = dm_read_reg(ctx, mmLB_SYNC_RESET_SEL); 133 + value = dm_read_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL)); 106 134 set_reg_field_value(value, 2, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL); 107 135 set_reg_field_value(value, 0, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2); 108 - dm_write_reg(ctx, mmLB_SYNC_RESET_SEL, value); 109 - 136 + dm_write_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL), value); 110 137 } 111 - 112 138 } 113 139 114 140 static void wait_for_fbc_state_changed( ··· 196 226 uint32_t addr; 197 227 uint32_t value, misc_value; 198 228 199 - 200 229 addr = mmFBC_CNTL; 201 230 value = dm_read_reg(compressor->ctx, addr); 202 231 set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); 232 + /* params->inst is valid HW CRTC instance start from 0 */ 203 233 set_reg_field_value( 204 234 value, 205 235 params->inst, ··· 208 238 209 239 /* Keep track of enum controller_id FBC is attached to */ 210 240 compressor->is_enabled = true; 211 - compressor->attached_inst = params->inst; 212 - cp110->offsets = reg_offsets[params->inst]; 241 + /* attached_inst is SW CRTC instance start from 1 242 + * 0 = CONTROLLER_ID_UNDEFINED means not attached crtc 243 + */ 244 + compressor->attached_inst = params->inst + CONTROLLER_ID_D0; 213 245 214 246 /* Toggle it as there is bug in HW */ 215 247 set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); ··· 240 268 void dce110_compressor_disable_fbc(struct compressor *compressor) 241 269 { 242 270 struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); 271 + uint32_t crtc_inst = 0; 243 272 244 273 if (compressor->options.bits.FBC_SUPPORT) { 245 - if (dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) { 274 + if (dce110_compressor_is_fbc_enabled_in_hw(compressor, &crtc_inst)) { 246 275 uint32_t reg_data; 247 276 /* Turn off compression */ 248 277 reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); ··· 257 284 wait_for_fbc_state_changed(cp110, false); 258 285 } 259 286 260 - /* Sync line buffer - dce100/110 only*/ 261 - reset_lb_on_vblank(compressor->ctx); 287 + /* Sync line buffer which fbc was attached to dce100/110 only */ 288 + if (crtc_inst > CONTROLLER_ID_UNDEFINED && crtc_inst < CONTROLLER_ID_D3) 289 + reset_lb_on_vblank(compressor, 290 + crtc_inst - CONTROLLER_ID_D0); 262 291 } 263 292 } 264 293 ··· 302 327 uint32_t fbc_pitch = 0; 303 328 uint32_t compressed_surf_address_low_part = 304 329 compressor->compr_surface_address.addr.low_part; 330 + 331 + cp110->offsets = reg_offsets[params->inst]; 305 332 306 333 /* Clear content first. */ 307 334 dm_write_reg( ··· 387 410 value = dm_read_reg(compressor->ctx, addr); 388 411 set_reg_field_value( 389 412 value, 390 - fbc_trigger | 391 - FBC_IDLE_FORCE_GRPH_COMP_EN | 392 - FBC_IDLE_FORCE_SRC_SEL_CHANGE | 393 - FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE | 394 - FBC_IDLE_FORCE_ALPHA_COMP_EN | 395 - FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN | 396 - FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF, 413 + fbc_trigger, 397 414 FBC_IDLE_FORCE_CLEAR_MASK, 398 415 FBC_IDLE_FORCE_CLEAR_MASK); 399 416 dm_write_reg(compressor->ctx, addr, value); ··· 520 549 compressor->base.channel_interleave_size = 0; 521 550 compressor->base.dram_channels_num = 0; 522 551 compressor->base.lpt_channels_num = 0; 523 - compressor->base.attached_inst = 0; 552 + compressor->base.attached_inst = CONTROLLER_ID_UNDEFINED; 524 553 compressor->base.is_enabled = false; 525 554 compressor->base.funcs = &dce110_compressor_funcs; 526 555
+34 -23
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
··· 1766 1766 * Check if FBC can be enabled 1767 1767 */ 1768 1768 static bool should_enable_fbc(struct dc *dc, 1769 - struct dc_state *context, 1770 - uint32_t *pipe_idx) 1769 + struct dc_state *context, 1770 + uint32_t *pipe_idx) 1771 1771 { 1772 1772 uint32_t i; 1773 1773 struct pipe_ctx *pipe_ctx = NULL; 1774 1774 struct resource_context *res_ctx = &context->res_ctx; 1775 + unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 1775 1776 1776 1777 1777 1778 ASSERT(dc->fbc_compressor); ··· 1787 1786 1788 1787 for (i = 0; i < dc->res_pool->pipe_count; i++) { 1789 1788 if (res_ctx->pipe_ctx[i].stream) { 1789 + 1790 1790 pipe_ctx = &res_ctx->pipe_ctx[i]; 1791 - *pipe_idx = i; 1792 - break; 1791 + 1792 + if (!pipe_ctx) 1793 + continue; 1794 + 1795 + /* fbc not applicable on underlay pipe */ 1796 + if (pipe_ctx->pipe_idx != underlay_idx) { 1797 + *pipe_idx = i; 1798 + break; 1799 + } 1793 1800 } 1794 1801 } 1795 1802 1796 - /* Pipe context should be found */ 1797 - ASSERT(pipe_ctx); 1803 + if (i == dc->res_pool->pipe_count) 1804 + return false; 1805 + 1806 + if (!pipe_ctx->stream->sink) 1807 + return false; 1808 + 1809 + if (!pipe_ctx->stream->sink->link) 1810 + return false; 1798 1811 1799 1812 /* Only supports eDP */ 1800 1813 if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP) ··· 1832 1817 /* 1833 1818 * Enable FBC 1834 1819 */ 1835 - static void enable_fbc(struct dc *dc, 1836 - struct dc_state *context) 1820 + static void enable_fbc( 1821 + struct dc *dc, 1822 + struct dc_state *context) 1837 1823 { 1838 1824 uint32_t pipe_idx = 0; 1839 1825 ··· 1844 1828 struct compressor *compr = dc->fbc_compressor; 1845 1829 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 1846 1830 1847 - 1848 1831 params.source_view_width = pipe_ctx->stream->timing.h_addressable; 1849 1832 params.source_view_height = pipe_ctx->stream->timing.v_addressable; 1850 - 1833 + params.inst = pipe_ctx->stream_res.tg->inst; 1851 1834 compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; 1852 1835 1853 1836 compr->funcs->surface_address_and_pitch(compr, &params); ··· 2061 2046 return status; 2062 2047 } 2063 2048 2064 - dcb->funcs->set_scratch_critical_state(dcb, false); 2065 - 2066 2049 if (dc->fbc_compressor) 2067 - enable_fbc(dc, context); 2050 + enable_fbc(dc, dc->current_state); 2051 + 2052 + dcb->funcs->set_scratch_critical_state(dcb, false); 2068 2053 2069 2054 return DC_OK; 2070 2055 } ··· 2423 2408 struct dc_plane_state *plane_state = pipe_ctx->plane_state; 2424 2409 struct xfm_grph_csc_adjustment adjust; 2425 2410 struct out_csc_color_matrix tbl_entry; 2426 - unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 2427 2411 unsigned int i; 2428 2412 DC_LOGGER_INIT(); 2429 2413 memset(&tbl_entry, 0, sizeof(tbl_entry)); ··· 2462 2448 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; 2463 2449 2464 2450 program_scaler(dc, pipe_ctx); 2465 - 2466 - /* fbc not applicable on Underlay pipe */ 2467 - if (dc->fbc_compressor && old_pipe->stream && 2468 - pipe_ctx->pipe_idx != underlay_idx) { 2469 - if (plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) 2470 - dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 2471 - else 2472 - enable_fbc(dc, dc->current_state); 2473 - } 2474 2451 2475 2452 mi->funcs->mem_input_program_surface_config( 2476 2453 mi, ··· 2539 2534 if (num_planes == 0) 2540 2535 return; 2541 2536 2537 + if (dc->fbc_compressor) 2538 + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 2539 + 2542 2540 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2543 2541 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2544 2542 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; ··· 2584 2576 (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) 2585 2577 dc->hwss.pipe_control_lock(dc, pipe_ctx, false); 2586 2578 } 2579 + 2580 + if (dc->fbc_compressor) 2581 + enable_fbc(dc, dc->current_state); 2587 2582 } 2588 2583 2589 2584 static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx)
+1
drivers/gpu/drm/amd/display/dc/inc/compressor.h
··· 77 77 }; 78 78 struct compressor { 79 79 struct dc_context *ctx; 80 + /* CONTROLLER_ID_D0 + instance, CONTROLLER_ID_UNDEFINED = 0 */ 80 81 uint32_t attached_inst; 81 82 bool is_enabled; 82 83 const struct compressor_funcs *funcs;