diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0303-drm-amd-display-use-CRTC_VERTICAL_INTERRUPT0-as-VBLA.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0303-drm-amd-display-use-CRTC_VERTICAL_INTERRUPT0-as-VBLA.patch | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0303-drm-amd-display-use-CRTC_VERTICAL_INTERRUPT0-as-VBLA.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0303-drm-amd-display-use-CRTC_VERTICAL_INTERRUPT0-as-VBLA.patch new file mode 100644 index 00000000..b129cef4 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0303-drm-amd-display-use-CRTC_VERTICAL_INTERRUPT0-as-VBLA.patch @@ -0,0 +1,392 @@ +From 4471b8747fd75ce79fcd219277cfabcb20c5d2c7 Mon Sep 17 00:00:00 2001 +From: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com> +Date: Thu, 23 Mar 2017 15:27:15 -0400 +Subject: [PATCH 0303/4131] drm/amd/display: use CRTC_VERTICAL_INTERRUPT0 as + VBLANK trigger. + +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> +--- + .../display/dc/dce110/dce110_timing_generator.c | 46 ++++++++++++++- + .../display/dc/dce110/dce110_timing_generator.h | 3 + + .../display/dc/dce120/dce120_timing_generator.c | 32 +++++++++- + .../amd/display/dc/dce80/dce80_timing_generator.c | 1 + + .../drm/amd/display/dc/inc/hw/timing_generator.h | 2 + + .../amd/display/dc/irq/dce110/irq_service_dce110.c | 68 +++++++++++++++------- + .../amd/display/dc/irq/dce110/irq_service_dce110.h | 5 ++ + .../amd/display/dc/irq/dce120/irq_service_dce120.c | 11 ++-- + .../amd/display/dc/irq/dce80/irq_service_dce80.c | 22 ++++--- + 9 files changed, 152 insertions(+), 38 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +index f4b8576..006412b 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c ++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +@@ -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( +diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +index 378509b..ca387b4 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h ++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +@@ -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__ */ +diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +index d7e787b..95cb176 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c ++++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +@@ -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, + }; + + +diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c +index eeccabd..1198f2f 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c ++++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c +@@ -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 = +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +index 62c1935..51902a4 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +@@ -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 +diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +index 4c7c85d..52361d1 100644 +--- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c ++++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +@@ -31,14 +31,10 @@ + + #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; +diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h +index a84f360..9237646 100644 +--- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h ++++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h +@@ -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 +diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c +index 5a263b2..3871633 100644 +--- a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c ++++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c +@@ -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() \ +diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c +index dd09d2b..7e8cb22 100644 +--- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c ++++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c +@@ -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() \ +-- +2.7.4 + |