drm/amd/display: use CRTC_VERTICAL_INTERRUPT0 as VBLANK trigger.
authorAndrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Thu, 23 Mar 2017 19:27:15 +0000 (15:27 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 26 Sep 2017 21:21:04 +0000 (17:21 -0400)
VBLANK interrupt is driven bu line buffer vcounter which is
ahead of CRTC vcounter. Use an interrupt that fires at the actual
CRTC vblank start boundry.

Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Reviewed-by: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h
drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c
drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c

index f4b8576a0546455303d620a90c90c813569e35f4..006412be7a02251ce7ea23735e2eb4f411169914 100644 (file)
@@ -1869,6 +1869,48 @@ void dce110_tg_set_colors(struct timing_generator *tg,
                dce110_tg_set_overscan_color(tg, overscan_color);
 }
 
+/* Gets first line of blank region of the display timing for CRTC
+ * and programms is as a trigger to fire vertical interrupt
+ */
+bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width)
+{
+       struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+       uint32_t vbl = 0;
+       uint32_t val = 0;
+       uint32_t position, vbl_start;
+
+       tg->funcs->get_scanoutpos(
+                       tg,
+                       &vbl,
+                       &position);
+
+       if (vbl == 0)
+               return false;
+
+       vbl_start =
+               get_reg_field_value(
+               vbl,
+               CRTC_V_BLANK_START_END,
+               CRTC_V_BLANK_START);
+
+       set_reg_field_value(
+               val,
+               vbl_start,
+               CRTC_VERTICAL_INTERRUPT0_POSITION,
+               CRTC_VERTICAL_INTERRUPT0_LINE_START);
+
+       /* Set interaval width for interrupt to fire to 1 scanline */
+       set_reg_field_value(
+               val,
+               vbl_start + width,
+               CRTC_VERTICAL_INTERRUPT0_POSITION,
+               CRTC_VERTICAL_INTERRUPT0_LINE_END);
+
+       dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERTICAL_INTERRUPT0_POSITION), val);
+
+       return true;
+}
+
 static const struct timing_generator_funcs dce110_tg_funcs = {
                .validate_timing = dce110_tg_validate_timing,
                .program_timing = dce110_tg_program_timing,
@@ -1901,8 +1943,8 @@ static const struct timing_generator_funcs dce110_tg_funcs = {
                                dce110_timing_generator_set_drr,
                .set_static_screen_control =
                        dce110_timing_generator_set_static_screen_control,
-               .set_test_pattern = dce110_timing_generator_set_test_pattern
-
+               .set_test_pattern = dce110_timing_generator_set_test_pattern,
+               .arm_vert_intr = dce110_arm_vert_intr,
 };
 
 bool dce110_timing_generator_construct(
index 378509b8e56c632bf91709c22c7349dbd9b03bea..ca387b40fc67acc52f364d81ce1b46f85a6f331f 100644 (file)
@@ -271,4 +271,7 @@ void dce110_tg_set_colors(struct timing_generator *tg,
        const struct tg_color *blank_color,
        const struct tg_color *overscan_color);
 
+bool dce110_arm_vert_intr(
+               struct timing_generator *tg, uint8_t width);
+
 #endif /* __DC_TIMING_GENERATOR_DCE110_H__ */
index d7e787b591a0a0977b3cf236ad5e5f2f50fe2058..95cb1768aeb54516d5d7e475162bed3bc281342d 100644 (file)
@@ -1039,6 +1039,35 @@ void dce120_timing_generator_set_test_pattern(
        }
 }
 
+static bool dce120_arm_vert_intr(
+               struct timing_generator *tg,
+               uint8_t width)
+{
+       struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+       uint32_t vbl, position, vbl_start;
+
+       tg->funcs->get_scanoutpos(
+                               tg,
+                               &vbl,
+                               &position);
+
+       if (vbl == 0)
+               return false;
+
+       vbl_start =
+               get_reg_field_value(
+               vbl,
+               CRTC0_CRTC_V_BLANK_START_END,
+               CRTC_V_BLANK_START);
+
+       CRTC_REG_SET_2(
+                       CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION,
+                       CRTC_VERTICAL_INTERRUPT0_LINE_START, vbl_start,
+                       CRTC_VERTICAL_INTERRUPT0_LINE_END, vbl_start + width);
+
+       return true;
+}
+
 static struct timing_generator_funcs dce120_tg_funcs = {
                .validate_timing = dce120_tg_validate_timing,
                .program_timing = dce120_tg_program_timing,
@@ -1068,7 +1097,8 @@ static struct timing_generator_funcs dce120_tg_funcs = {
                .enable_advanced_request = dce120_timing_generator_enable_advanced_request,
                .set_drr = dce120_timing_generator_set_drr,
                .set_static_screen_control = dce120_timing_generator_set_static_screen_control,
-               .set_test_pattern = dce120_timing_generator_set_test_pattern
+               .set_test_pattern = dce120_timing_generator_set_test_pattern,
+               .arm_vert_intr = dce120_arm_vert_intr,
 };
 
 
index eeccabd65a7ab89fd82e799149aeddcfb0c3acd2..1198f2fbf9c7a712bca68abdbe0af78ddf47b2ec 100644 (file)
@@ -145,6 +145,7 @@ static const struct timing_generator_funcs dce80_tg_funcs = {
                .set_static_screen_control =
                        dce110_timing_generator_set_static_screen_control,
                .set_test_pattern = dce110_timing_generator_set_test_pattern,
+               .arm_vert_intr = dce110_arm_vert_intr,
 
                /* DCE8.0 overrides */
                .enable_advanced_request =
index 62c19358254b0aa75d3f288f24b38fcb2cda17ad..51902a4f8798a4350a9ef6e5f9ef92441333b4d8 100644 (file)
@@ -156,6 +156,8 @@ struct timing_generator_funcs {
                enum controller_dp_test_pattern test_pattern,
                enum dc_color_depth color_depth);
 
+       bool (*arm_vert_intr)(struct timing_generator *tg, uint8_t width);
+
 };
 
 #endif
index 4c7c85d455185300d4e2ca579157638bc5be1277..52361d1472faeb2147a8d9ae01dd7e2e3abb8dbb 100644 (file)
 
 #include "dce/dce_11_0_d.h"
 #include "dce/dce_11_0_sh_mask.h"
+
 #include "ivsrcid/ivsrcid_vislands30.h"
 
-#define VISLANDS30_IV_SRCID_D1_VBLANK                        1
-#define VISLANDS30_IV_SRCID_D2_VBLANK                        2
-#define VISLANDS30_IV_SRCID_D3_VBLANK                        3
-#define VISLANDS30_IV_SRCID_D4_VBLANK                        4
-#define VISLANDS30_IV_SRCID_D5_VBLANK                        5
-#define VISLANDS30_IV_SRCID_D6_VBLANK                        6
+#include "core_dc.h"
 
 static bool hpd_ack(
        struct irq_service *irq_service,
@@ -83,7 +79,7 @@ static const struct irq_source_info_funcs pflip_irq_info_funcs = {
 };
 
 static const struct irq_source_info_funcs vblank_irq_info_funcs = {
-       .set = NULL,
+       .set = dce110_vblank_set,
        .ack = NULL
 };
 
@@ -148,18 +144,19 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = {
 
 #define vblank_int_entry(reg_num)\
        [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\
-               .enable_reg = mmLB ## reg_num ## _LB_INTERRUPT_MASK,\
+               .enable_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\
                .enable_mask =\
-                       LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\
+               CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
                .enable_value = {\
-                       LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\
-                       ~LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK},\
-               .ack_reg = mmLB ## reg_num ## _LB_VBLANK_STATUS,\
+                       CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
+                       ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\
+               .ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\
                .ack_mask =\
-               LB_VBLANK_STATUS__VBLANK_ACK_MASK,\
+               CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\
                .ack_value =\
-               LB_VBLANK_STATUS__VBLANK_ACK_MASK,\
-               .funcs = &vblank_irq_info_funcs\
+               CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\
+               .funcs = &vblank_irq_info_funcs,\
+               .src_id = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 + reg_num\
        }
 
 #define dummy_irq_entry() \
@@ -202,6 +199,35 @@ bool dal_irq_service_dummy_ack(
        return false;
 }
 
+
+bool dce110_vblank_set(
+               struct irq_service *irq_service,
+               const struct irq_source_info *info,
+               bool enable)
+{
+       struct dc_context *dc_ctx = irq_service->ctx;
+       struct core_dc *core_dc = DC_TO_CORE(irq_service->ctx->dc);
+       enum dc_irq_source dal_irq_src = dc_interrupt_to_irq_source(
+                                                                               irq_service->ctx->dc,
+                                                                               info->src_id,
+                                                                               info->ext_id);
+       uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK;
+
+       struct timing_generator *tg =
+                       core_dc->current_context->res_ctx.pipe_ctx[pipe_offset].tg;
+
+       if (enable) {
+               if (!tg->funcs->arm_vert_intr(tg, 2)) {
+                       DC_ERROR("Failed to get VBLANK!\n");
+                       return false;
+               }
+       }
+
+       dal_irq_service_set_generic(irq_service, info, enable);
+       return true;
+
+}
+
 static const struct irq_source_info_funcs dummy_irq_info_funcs = {
        .set = dal_irq_service_dummy_set,
        .ack = dal_irq_service_dummy_ack
@@ -302,17 +328,17 @@ enum dc_irq_source to_dal_irq_source_dce110(
                uint32_t ext_id)
 {
        switch (src_id) {
-       case VISLANDS30_IV_SRCID_D1_VBLANK:
+       case VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0:
                return DC_IRQ_SOURCE_VBLANK1;
-       case VISLANDS30_IV_SRCID_D2_VBLANK:
+       case VISLANDS30_IV_SRCID_D2_VERTICAL_INTERRUPT0:
                return DC_IRQ_SOURCE_VBLANK2;
-       case VISLANDS30_IV_SRCID_D3_VBLANK:
+       case VISLANDS30_IV_SRCID_D3_VERTICAL_INTERRUPT0:
                return DC_IRQ_SOURCE_VBLANK3;
-       case VISLANDS30_IV_SRCID_D4_VBLANK:
+       case VISLANDS30_IV_SRCID_D4_VERTICAL_INTERRUPT0:
                return DC_IRQ_SOURCE_VBLANK4;
-       case VISLANDS30_IV_SRCID_D5_VBLANK:
+       case VISLANDS30_IV_SRCID_D5_VERTICAL_INTERRUPT0:
                return DC_IRQ_SOURCE_VBLANK5;
-       case VISLANDS30_IV_SRCID_D6_VBLANK:
+       case VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0:
                return DC_IRQ_SOURCE_VBLANK6;
        case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT:
                return DC_IRQ_SOURCE_VUPDATE1;
index a84f360c6515bc37d271f2774152df225f1f1bdc..9237646c0959523f892087752da16d107dbb81aa 100644 (file)
@@ -45,4 +45,9 @@ bool dal_irq_service_dummy_ack(
        struct irq_service *irq_service,
        const struct irq_source_info *info);
 
+bool dce110_vblank_set(
+       struct irq_service *irq_service,
+       const struct irq_source_info *info,
+       bool enable);
+
 #endif
index 5a263b2efa515e1f40c447743bb8da87744613f9..3871633ac6359964e9228e15681cbc9c75cc7593 100644 (file)
@@ -79,7 +79,7 @@ static const struct irq_source_info_funcs pflip_irq_info_funcs = {
 };
 
 static const struct irq_source_info_funcs vblank_irq_info_funcs = {
-       .set = NULL,
+       .set = dce110_vblank_set,
        .ack = NULL
 };
 
@@ -144,10 +144,11 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = {
 
 #define vblank_int_entry(reg_num)\
        [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\
-               IRQ_REG_ENTRY(LB, reg_num,\
-                       LB_INTERRUPT_MASK, VBLANK_INTERRUPT_MASK,\
-                       LB_VBLANK_STATUS, VBLANK_ACK),\
-               .funcs = &vblank_irq_info_funcs\
+               IRQ_REG_ENTRY(CRTC, reg_num,\
+                               CRTC_VERTICAL_INTERRUPT0_CONTROL, CRTC_VERTICAL_INTERRUPT0_INT_ENABLE,\
+                               CRTC_VERTICAL_INTERRUPT0_CONTROL, CRTC_VERTICAL_INTERRUPT0_CLEAR),\
+               .funcs = &vblank_irq_info_funcs,\
+               .src_id = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 + reg_num\
        }
 
 #define dummy_irq_entry() \
index dd09d2b6d4a76ff13bf92cb9a3f7b3d0ed6702f3..7e8cb22f280f8aa3c56a8c4cc5d21897656efde7 100644 (file)
@@ -35,6 +35,9 @@
 
 #include "ivsrcid/ivsrcid_vislands30.h"
 
+#include "dc_types.h"
+#include "inc/core_dc.h"
+
 static bool hpd_ack(
        struct irq_service *irq_service,
        const struct irq_source_info *info)
@@ -78,7 +81,7 @@ static const struct irq_source_info_funcs pflip_irq_info_funcs = {
 };
 
 static const struct irq_source_info_funcs vblank_irq_info_funcs = {
-       .set = NULL,
+       .set = dce110_vblank_set,
        .ack = NULL
 };
 
@@ -145,18 +148,19 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = {
 
 #define vblank_int_entry(reg_num)\
        [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\
-               .enable_reg = mmLB ## reg_num ## _LB_INTERRUPT_MASK,\
+               .enable_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\
                .enable_mask =\
-                       LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\
+               CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
                .enable_value = {\
-                       LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\
-                       ~LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK},\
-               .ack_reg = mmLB ## reg_num ## _LB_VBLANK_STATUS,\
+                       CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
+                       ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\
+               .ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\
                .ack_mask =\
-               LB_VBLANK_STATUS__VBLANK_ACK_MASK,\
+               CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\
                .ack_value =\
-               LB_VBLANK_STATUS__VBLANK_ACK_MASK,\
-               .funcs = &vblank_irq_info_funcs\
+               CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\
+               .funcs = &vblank_irq_info_funcs,\
+               .src_id = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 + reg_num\
        }
 
 #define dummy_irq_entry() \