]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/amd/display: Fix FBC text console corruption
authorRoman Li <roman.li@amd.com>
Thu, 29 Mar 2018 15:14:25 +0000 (11:14 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 12 Apr 2018 18:55:55 +0000 (13:55 -0500)
Signed-off-by: Roman Li <roman.li@amd.com>
Reviewed-by: Charlene Liu <Charlene.Liu@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c

index 775d3bf0bd3956dfeed77c7b6718ac4635bba093..9150d26944508e4a91ec5d16af7cb2d6fa3b589e 100644 (file)
@@ -102,6 +102,43 @@ static uint32_t align_to_chunks_number_per_line(uint32_t pixels)
        return 256 * ((pixels + 255) / 256);
 }
 
+static void reset_lb_on_vblank(struct dc_context *ctx)
+{
+       uint32_t value, frame_count;
+       uint32_t retry = 0;
+       uint32_t status_pos =
+                       dm_read_reg(ctx, mmCRTC_STATUS_POSITION);
+
+
+       /* Only if CRTC is enabled and counter is moving we wait for one frame. */
+       if (status_pos != dm_read_reg(ctx, mmCRTC_STATUS_POSITION)) {
+               /* Resetting LB on VBlank */
+               value = dm_read_reg(ctx, mmLB_SYNC_RESET_SEL);
+               set_reg_field_value(value, 3, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL);
+               set_reg_field_value(value, 1, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2);
+               dm_write_reg(ctx, mmLB_SYNC_RESET_SEL, value);
+
+               frame_count = dm_read_reg(ctx, mmCRTC_STATUS_FRAME_COUNT);
+
+
+               for (retry = 100; retry > 0; retry--) {
+                       if (frame_count != dm_read_reg(ctx, mmCRTC_STATUS_FRAME_COUNT))
+                               break;
+                       msleep(1);
+               }
+               if (!retry)
+                       dm_error("Frame count did not increase for 100ms.\n");
+
+               /* Resetting LB on VBlank */
+               value = dm_read_reg(ctx, mmLB_SYNC_RESET_SEL);
+               set_reg_field_value(value, 2, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL);
+               set_reg_field_value(value, 0, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2);
+               dm_write_reg(ctx, mmLB_SYNC_RESET_SEL, value);
+
+       }
+
+}
+
 static void wait_for_fbc_state_changed(
        struct dce110_compressor *cp110,
        bool enabled)
@@ -232,19 +269,23 @@ void dce110_compressor_disable_fbc(struct compressor *compressor)
 {
        struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
 
-       if (compressor->options.bits.FBC_SUPPORT &&
-               dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) {
-               uint32_t reg_data;
-               /* Turn off compression */
-               reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL);
-               set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
-               dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data);
-
-               /* Reset enum controller_id to undefined */
-               compressor->attached_inst = 0;
-               compressor->is_enabled = false;
-
-               wait_for_fbc_state_changed(cp110, false);
+       if (compressor->options.bits.FBC_SUPPORT) {
+               if (dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) {
+                       uint32_t reg_data;
+                       /* Turn off compression */
+                       reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL);
+                       set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
+                       dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data);
+
+                       /* Reset enum controller_id to undefined */
+                       compressor->attached_inst = 0;
+                       compressor->is_enabled = false;
+
+                       wait_for_fbc_state_changed(cp110, false);
+               }
+
+               /* Sync line buffer  - dce100/110 only*/
+               reset_lb_on_vblank(compressor->ctx);
        }
 }