[PATCH 05/12] drm/amd/display: use CRTC_VERTICAL_INTERRUPT0 as VBLANK trigger.
Harry Wentland
harry.wentland at amd.com
Tue Mar 28 21:09:48 UTC 2017
From: Andrey Grodzovsky <Andrey.Grodzovsky at amd.com>
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.
Change-Id: I2d397447e105137451c966ddfc73f533f0d8bc4b
Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky at amd.com>
Acked-by: Harry Wentland <Harry.Wentland at amd.com>
Reviewed-by: Andrey Grodzovsky <Andrey.Grodzovsky at 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 f4b8576a0546..006412be7a02 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 378509b8e56c..ca387b40fc67 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 d7e787b591a0..95cb1768aeb5 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 eeccabd65a7a..1198f2fbf9c7 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 62c19358254b..51902a4f8798 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 4c7c85d45518..52361d1472fa 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 a84f360c6515..9237646c0959 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 5a263b2efa51..3871633ac635 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 dd09d2b6d4a7..7e8cb22f280f 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.11.0
More information about the amd-gfx
mailing list