aboutsummaryrefslogtreecommitdiffstats
path: root/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0303-drm-amd-display-use-CRTC_VERTICAL_INTERRUPT0-as-VBLA.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0303-drm-amd-display-use-CRTC_VERTICAL_INTERRUPT0-as-VBLA.patch')
-rw-r--r--meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0303-drm-amd-display-use-CRTC_VERTICAL_INTERRUPT0-as-VBLA.patch392
1 files changed, 392 insertions, 0 deletions
diff --git a/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0303-drm-amd-display-use-CRTC_VERTICAL_INTERRUPT0-as-VBLA.patch b/meta-v1000/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-v1000/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
+