[PATCH] drm/amd/display: Fix p-state allow debug index on dcn31

2022-03-18 Thread Nicholas Kazlauskas
[Why]
It changed since dcn30 but the hubbub31 constructor hasn't been
modified to reflect this.

[How]
Update the value in the constructor to 0x6 so we're checking the right
bits for p-state allow.

It worked before by accident, but can falsely assert 0 depending on HW
state transitions. The most frequent of which appears to be when
all pipes turn off during IGT tests.

Cc: Harry Wentland 
Fixes: d158560fc0e1 ("drm/amd/display: Add pstate verification and recovery for 
DCN31")
Signed-off-by: Nicholas Kazlauskas 
Reviewed-by: Eric Yang 
---
 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c 
b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
index 3e6d6ebd199e..51c5f3685470 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
@@ -1042,5 +1042,7 @@ void hubbub31_construct(struct dcn20_hubbub *hubbub31,
hubbub31->detile_buf_size = det_size_kb * 1024;
hubbub31->pixel_chunk_size = pixel_chunk_size_kb * 1024;
hubbub31->crb_size_segs = config_return_buffer_size_kb / 
DCN31_CRB_SEGMENT_SIZE_KB;
+
+   hubbub31->debug_test_index_pstate = 0x6;
 }
 
-- 
2.25.1



[PATCH] drm/amd/display: Add pstate verification and recovery for DCN31

2022-03-09 Thread Nicholas Kazlauskas
[Why]
To debug when p-state is being blocked and avoid PMFW hangs when
it does occur.

[How]
Re-use the DCN10 hardware sequencer by adding a new interface for
verifying p-state high on the hubbub. The interface is mostly the
same as the DCN10 interface, but the bit definitions have changed for
the debug bus.

Signed-off-by: Nicholas Kazlauskas 
Reviewed-by: Eric Yang 
---
 .../drm/amd/display/dc/dcn10/dcn10_hubbub.c   |  1 +
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 10 +++-
 .../drm/amd/display/dc/dcn30/dcn30_hubbub.c   |  1 +
 .../drm/amd/display/dc/dcn301/dcn301_hubbub.c |  1 +
 .../drm/amd/display/dc/dcn31/dcn31_hubbub.c   | 60 +++
 .../drm/amd/display/dc/dcn31/dcn31_resource.c |  2 +-
 .../gpu/drm/amd/display/dc/inc/hw/dchubbub.h  |  2 +
 7 files changed, 73 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
index f4f423d0b8c3..80595d7f060c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
@@ -940,6 +940,7 @@ static const struct hubbub_funcs hubbub1_funcs = {
.program_watermarks = hubbub1_program_watermarks,
.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
.allow_self_refresh_control = hubbub1_allow_self_refresh_control,
+   .verify_allow_pstate_change_high = 
hubbub1_verify_allow_pstate_change_high,
 };
 
 void hubbub1_construct(struct hubbub *hubbub,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index bc9dd48258e3..c3e141c19a77 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -1112,9 +1112,13 @@ static bool dcn10_hw_wa_force_recovery(struct dc *dc)
 
 void dcn10_verify_allow_pstate_change_high(struct dc *dc)
 {
+   struct hubbub *hubbub = dc->res_pool->hubbub;
static bool should_log_hw_state; /* prevent hw state log by default */
 
-   if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) {
+   if (!hubbub->funcs->verify_allow_pstate_change_high)
+   return;
+
+   if (!hubbub->funcs->verify_allow_pstate_change_high(hubbub)) {
int i = 0;
 
if (should_log_hw_state)
@@ -1123,8 +1127,8 @@ void dcn10_verify_allow_pstate_change_high(struct dc *dc)
TRACE_DC_PIPE_STATE(pipe_ctx, i, MAX_PIPES);
BREAK_TO_DEBUGGER();
if (dcn10_hw_wa_force_recovery(dc)) {
-   /*check again*/
-   if 
(!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub))
+   /*check again*/
+   if 
(!hubbub->funcs->verify_allow_pstate_change_high(hubbub))
BREAK_TO_DEBUGGER();
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c 
b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c
index f4414de96acc..152c9c5733f1 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c
@@ -448,6 +448,7 @@ static const struct hubbub_funcs hubbub30_funcs = {
.program_watermarks = hubbub3_program_watermarks,
.allow_self_refresh_control = hubbub1_allow_self_refresh_control,
.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
+   .verify_allow_pstate_change_high = 
hubbub1_verify_allow_pstate_change_high,
.force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes,
.force_pstate_change_control = hubbub3_force_pstate_change_control,
.init_watermarks = hubbub3_init_watermarks,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c 
b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c
index 1e3bd2e9cdcc..a046664e2031 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c
@@ -60,6 +60,7 @@ static const struct hubbub_funcs hubbub301_funcs = {
.program_watermarks = hubbub3_program_watermarks,
.allow_self_refresh_control = hubbub1_allow_self_refresh_control,
.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
+   .verify_allow_pstate_change_high = 
hubbub1_verify_allow_pstate_change_high,
.force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes,
.force_pstate_change_control = hubbub3_force_pstate_change_control,
.hubbub_read_state = hubbub2_read_state,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c 
b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
index 5e3bcaf12cac..3e6d6ebd199e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbu

[PATCH] drm/amd/display: Call dc_stream_release for remove link enc assignment

2022-01-24 Thread Nicholas Kazlauskas
[Why]
A porting error resulted in the stream assignment for the link
being retained without being released - a memory leak.

[How]
Fix the porting error by adding back the dc_stream_release() intended
as part of the original patch.

Fixes: 2e45b19dd882 ("drm/amd/display: retain/release at proper places in 
link_enc assignment")

Cc: Qingqing Zhuo 
Cc: Aurabindo Pillai 
Cc: Rodrigo Siqueira 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c
index a55944da8d53..00f72f66a7ef 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c
@@ -122,6 +122,7 @@ static void remove_link_enc_assignment(
stream->link_enc = NULL;

state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].eng_id = 
ENGINE_ID_UNKNOWN;

state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].stream = NULL;
+   dc_stream_release(stream);
break;
}
}
-- 
2.25.1



[PATCH] drm/amd/display: Fix out of bounds access on DNC31 stream encoder regs

2021-12-07 Thread Nicholas Kazlauskas
[Why]
During dcn31_stream_encoder_create, if PHYC/D get remapped to F/G on B0
then we'll index 5 or 6 into a array of length 5 - leading to an
access violation on some configs during device creation.

[How]
Software won't be touching PHYF/PHYG directly, so just extend the
array to cover all possible engine IDs.

Even if it does by try to access one of these registers by accident
the offset will be 0 and we'll get a warning during the access.

Fixes: 2fe9a0e1173f ("drm/amd/display: Fix DCN3 B0 DP Alt Mapping")
Cc: Mario Limonciello 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c 
b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
index ec5b4cec0ef2..04b52c9d18da 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
@@ -485,7 +485,8 @@ static const struct dcn31_apg_mask apg_mask = {
SE_DCN3_REG_LIST(id)\
 }
 
-static const struct dcn10_stream_enc_registers stream_enc_regs[] = {
+/* Some encoders won't be initialized here - but they're logical, not 
physical. */
+static const struct dcn10_stream_enc_registers 
stream_enc_regs[ENGINE_ID_COUNT] = {
stream_enc_regs(0),
stream_enc_regs(1),
stream_enc_regs(2),
-- 
2.25.1



[PATCH] drm/amdgpu/display: Only set vblank_disable_immediate when PSR is not enabled

2021-11-30 Thread Nicholas Kazlauskas
[Why]
PSR currently relies on the kernel's delayed vblank on/off mechanism
as an implicit bufferring mechanism to prevent excessive entry/exit.

Without this delay the user experience is impacted since it can take
a few frames to enter/exit.

[How]
Only allow vblank disable immediate for DC when psr is not supported.

Leave a TODO indicating that this support should be extended in the
future to delay independent of the vblank interrupt.

Fixes: 3d1508b73ff1 ("drm/amdgpu/display: set vblank_disable_immediate for DC")

Cc: Harry Wentland 
Cc: Alex Deucher 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0747dc7922c2..d582d44c02ad 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1599,9 +1599,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
adev_to_drm(adev)->mode_config.cursor_width = 
adev->dm.dc->caps.max_cursor_size;
adev_to_drm(adev)->mode_config.cursor_height = 
adev->dm.dc->caps.max_cursor_size;
 
-   /* Disable vblank IRQs aggressively for power-saving */
-   adev_to_drm(adev)->vblank_disable_immediate = true;
-
if (drm_vblank_init(adev_to_drm(adev), adev->dm.display_indexes_num)) {
DRM_ERROR(
"amdgpu: failed to initialize sw for display support.\n");
@@ -4264,6 +4261,14 @@ static int amdgpu_dm_initialize_drm_device(struct 
amdgpu_device *adev)
 
}
 
+   /*
+* Disable vblank IRQs aggressively for power-saving.
+*
+* TODO: Fix vblank control helpers to delay PSR entry to allow this 
when PSR
+* is also supported.
+*/
+   adev_to_drm(adev)->vblank_disable_immediate = !psr_feature_enabled;
+
/* Software is initialized. Now we can register interrupt handlers. */
switch (adev->asic_type) {
 #if defined(CONFIG_DRM_AMD_DC_SI)
-- 
2.25.1



[PATCH 5/5] drm/amd/display: Enable dpia in dmub only for DCN31 B0

2021-10-25 Thread Nicholas Kazlauskas
From: Jude Shih 

[Why]
DMUB binary is common for both A0 and B0. Hence, driver should
notify FW about the support for DPIA in B0.

[How]
Added dpia_supported bit in dmub_fw_boot_options and will be set
only for B0.

Assign dpia_supported to true before dm_dmub_hw_init
in B0 case.

Signed-off-by: Jude Shih 
Reviewed-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 
 drivers/gpu/drm/amd/display/dmub/dmub_srv.h   |  1 +
 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c |  1 +
 3 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0ad6d0e2a2d8..139a7707f317 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1017,6 +1017,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
const unsigned char *fw_inst_const, *fw_bss_data;
uint32_t i, fw_inst_const_size, fw_bss_data_size;
bool has_hw_support;
+   struct dc *dc = adev->dm.dc;
 
if (!dmub_srv)
/* DMUB isn't supported on the ASIC. */
@@ -1103,6 +1104,17 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
for (i = 0; i < fb_info->num_fb; ++i)
hw_params.fb[i] = _info->fb[i];
 
+   switch (adev->asic_type) {
+   case CHIP_YELLOW_CARP:
+   if (dc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_A0) {
+   hw_params.dpia_supported = true;
+   hw_params.disable_dpia = 
dc->debug.dpia_debug.bits.disable_dpia;
+   }
+   break;
+   default:
+   break;
+   }
+
status = dmub_srv_hw_init(dmub_srv, _params);
if (status != DMUB_STATUS_OK) {
DRM_ERROR("Error initializing DMUB HW: %d\n", status);
diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h 
b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
index 6c4f0ada163f..717c0e572d2f 100644
--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
@@ -238,6 +238,7 @@ struct dmub_srv_hw_params {
bool load_inst_const;
bool skip_panel_power_sequence;
bool disable_z10;
+   bool dpia_supported;
bool disable_dpia;
 };
 
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c 
b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
index 5df990277dd4..10ebf20eaa41 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
@@ -338,6 +338,7 @@ void dmub_dcn31_enable_dmub_boot_options(struct dmub_srv 
*dmub, const struct dmu
union dmub_fw_boot_options boot_options = {0};
 
boot_options.bits.z10_disable = params->disable_z10;
+   boot_options.bits.dpia_supported = params->dpia_supported;
boot_options.bits.enable_dpia = params->disable_dpia ? 0 : 1;
 
boot_options.bits.sel_mux_phy_c_d_phy_f_g = (dmub->asic == 
DMUB_ASIC_DCN31B) ? 1 : 0;
-- 
2.25.1



[PATCH 3/5] drm/amd/display: Fix USB4 hot plug crash issue

2021-10-25 Thread Nicholas Kazlauskas
From: Jude Shih 

[Why]
Notify data from outbox corrupt, the notify type should be 2 (HPD) instead of 0
(No data). We copied the address instead of the value. The memory might be
freed in the end of outbox IRQ

[How]
We should allocate the memory of notify and copy the whole content from outbox 
to
hpd handle function

Fixes: 5cecad78ea53 ("drm/amd/display: Support for SET_CONFIG processing with 
DMUB")
Signed-off-by: Jude Shih 
Reviewed-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 +--
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 4cd64529b180..0ad6d0e2a2d8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -730,6 +730,8 @@ static void dm_handle_hpd_work(struct work_struct *work)

dmub_hpd_wrk->adev->dm.dmub_callback[dmub_hpd_wrk->dmub_notify->type](dmub_hpd_wrk->adev,
dmub_hpd_wrk->dmub_notify);
}
+
+   kfree(dmub_hpd_wrk->dmub_notify);
kfree(dmub_hpd_wrk);
 
 }
@@ -755,12 +757,6 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
 
if (dc_enable_dmub_notifications(adev->dm.dc) &&
irq_params->irq_src == DC_IRQ_SOURCE_DMCUB_OUTBOX) {
-   dmub_hpd_wrk = kzalloc(sizeof(*dmub_hpd_wrk), GFP_ATOMIC);
-   if (!dmub_hpd_wrk) {
-   DRM_ERROR("Failed to allocate dmub_hpd_wrk");
-   return;
-   }
-   INIT_WORK(_hpd_wrk->handle_hpd_work, dm_handle_hpd_work);
 
do {
dc_stat_get_dmub_notification(adev->dm.dc, );
@@ -769,7 +765,20 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
continue;
}
if (dm->dmub_thread_offload[notify.type] == true) {
-   dmub_hpd_wrk->dmub_notify = 
+   dmub_hpd_wrk = kzalloc(sizeof(*dmub_hpd_wrk), 
GFP_ATOMIC);
+   if (!dmub_hpd_wrk) {
+   DRM_ERROR("Failed to allocate 
dmub_hpd_wrk");
+   return;
+   }
+   dmub_hpd_wrk->dmub_notify = 
kzalloc(sizeof(struct dmub_notification), GFP_ATOMIC);
+   if (!dmub_hpd_wrk->dmub_notify) {
+   kfree(dmub_hpd_wrk);
+   DRM_ERROR("Failed to allocate 
dmub_hpd_wrk->dmub_notify");
+   return;
+   }
+   INIT_WORK(_hpd_wrk->handle_hpd_work, 
dm_handle_hpd_work);
+   if (dmub_hpd_wrk->dmub_notify)
+   memcpy(dmub_hpd_wrk->dmub_notify, 
, sizeof(struct dmub_notification));
dmub_hpd_wrk->adev = adev;
if (notify.type == DMUB_NOTIFICATION_HPD) {
plink = 
adev->dm.dc->links[notify.link_index];
-- 
2.25.1



[PATCH 1/5] drm/amd/display: Fallback to clocks which meet requested voltage on DCN31

2021-10-25 Thread Nicholas Kazlauskas
From: Michael Strauss 

[WHY]
On certain configs, SMU clock table voltages don't match which cause parser
to behave incorrectly by leaving dcfclk and socclk table entries unpopulated.

[HOW]
Currently the function that finds the corresponding clock for a given voltage
only checks for exact voltage level matches. In the case that no match gets
found, parser now falls back to searching for the max clock which meets the
requested voltage (i.e. its corresponding voltage is below requested).

Signed-off-by: Michael Strauss 
Reviewed-by: Nicholas Kazlauskas 
---
 .../amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c| 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c 
b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
index 0088dff441da..f4c9a458ace8 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
@@ -523,14 +523,21 @@ static unsigned int find_clk_for_voltage(
unsigned int voltage)
 {
int i;
+   int max_voltage = 0;
+   int clock = 0;
 
for (i = 0; i < NUM_SOC_VOLTAGE_LEVELS; i++) {
-   if (clock_table->SocVoltage[i] == voltage)
+   if (clock_table->SocVoltage[i] == voltage) {
return clocks[i];
+   } else if (clock_table->SocVoltage[i] >= max_voltage &&
+   clock_table->SocVoltage[i] < voltage) {
+   max_voltage = clock_table->SocVoltage[i];
+   clock = clocks[i];
+   }
}
 
-   ASSERT(0);
-   return 0;
+   ASSERT(clock);
+   return clock;
 }
 
 void dcn31_clk_mgr_helper_populate_bw_params(
-- 
2.25.1



[PATCH 4/5] drm/amd/display: MST support for DPIA

2021-10-25 Thread Nicholas Kazlauskas
From: Meenakshikumar Somasundaram 

[Why]
- DPIA MST slot registers are not programmed during payload
allocation and hence MST does not work with DPIA.
- HPD RX interrupts are not handled for DPIA.

[How]
- Added inbox command to program the MST slots whenever
  payload allocation happens for DPIA links.
- Added support for handling HPD RX interrupts

Signed-off-by: Meenakshikumar Somasundaram 
Reviewed-by: Jun Lei 
Acked-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/core/dc.c  | 54 +++
 drivers/gpu/drm/amd/display/dc/core/dc_link.c | 28 ++
 drivers/gpu/drm/amd/display/dc/dc.h   |  6 +++
 .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   | 23 
 4 files changed, 111 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 9d33b00b7e27..12e5470fa567 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3750,6 +3750,60 @@ bool dc_process_dmub_set_config_async(struct dc *dc,
return is_cmd_complete;
 }
 
+/**
+ *
+ *  Function: dc_process_dmub_set_mst_slots
+ *
+ *  @brief
+ * Submits mst slot allocation command to dmub via inbox message
+ *
+ *  @param
+ * [in] dc: dc structure
+ * [in] link_index: link index
+ * [in] mst_alloc_slots: mst slots to be allotted
+ * [out] mst_slots_in_use: mst slots in use returned in failure 
case
+ *
+ * @return
+ * DC_OK if successful, DC_ERROR if failure
+ *
+ */
+enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
+   uint32_t link_index,
+   uint8_t mst_alloc_slots,
+   uint8_t *mst_slots_in_use)
+{
+   union dmub_rb_cmd cmd = {0};
+   struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;
+
+   /* prepare MST_ALLOC_SLOTS command */
+   cmd.set_mst_alloc_slots.header.type = DMUB_CMD__DPIA;
+   cmd.set_mst_alloc_slots.header.sub_type = 
DMUB_CMD__DPIA_MST_ALLOC_SLOTS;
+
+   cmd.set_mst_alloc_slots.mst_slots_control.instance = 
dc->links[link_index]->ddc_hw_inst;
+   cmd.set_mst_alloc_slots.mst_slots_control.mst_alloc_slots = 
mst_alloc_slots;
+
+   if (!dc_dmub_srv_cmd_with_reply_data(dmub_srv, ))
+   /* command is not processed by dmub */
+   return DC_ERROR_UNEXPECTED;
+
+   /* command processed by dmub, if ret_status is 1 */
+   if (cmd.set_config_access.header.ret_status != 1)
+   /* command processing error */
+   return DC_ERROR_UNEXPECTED;
+
+   /* command processed and we have a status of 2, mst not enabled in dpia 
*/
+   if (cmd.set_mst_alloc_slots.mst_slots_control.immed_status == 2)
+   return DC_FAIL_UNSUPPORTED_1;
+
+   /* previously configured mst alloc and used slots did not match */
+   if (cmd.set_mst_alloc_slots.mst_slots_control.immed_status == 3) {
+   *mst_slots_in_use = 
cmd.set_mst_alloc_slots.mst_slots_control.mst_slots_in_use;
+   return DC_NOT_SUPPORTED;
+   }
+
+   return DC_OK;
+}
+
 /**
  * dc_disable_accelerated_mode - disable accelerated mode
  * @dc: dc structure
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index 27b9ff98a569..2796bdd17de1 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -3499,6 +3499,20 @@ enum dc_status dc_link_allocate_mst_payload(struct 
pipe_ctx *pipe_ctx)
 
ASSERT(proposed_table.stream_count > 0);
 
+   if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
+   static enum dc_status status;
+   uint8_t mst_alloc_slots = 0, prev_mst_slots_in_use = 0xFF;
+
+   for (i = 0; i < link->mst_stream_alloc_table.stream_count; i++)
+   mst_alloc_slots += 
link->mst_stream_alloc_table.stream_allocations[i].slot_count;
+
+   status = dc_process_dmub_set_mst_slots(link->dc, 
link->link_index,
+   mst_alloc_slots, _mst_slots_in_use);
+   ASSERT(status == DC_OK);
+   DC_LOG_MST("dpia : status[%d]: alloc_slots[%d]: 
used_slots[%d]\n",
+   status, mst_alloc_slots, prev_mst_slots_in_use);
+   }
+
/* program DP source TX for payload */
 #if defined(CONFIG_DRM_AMD_DC_DCN)
switch (dp_get_link_encoding_format(>cur_link_settings)) {
@@ -3842,6 +3856,20 @@ static enum dc_status deallocate_mst_payload(struct 
pipe_ctx *pipe_ctx)
 #endif
}
 
+   if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
+   enum dc_status status;
+   uint8_t 

[PATCH 2/5] drm/amd/display: Fix deadlock when falling back to v2 from v3

2021-10-25 Thread Nicholas Kazlauskas
[Why]
A deadlock in the kernel occurs when we fallback from the V3 to V2
add_topology_to_display or remove_topology_to_display because they
both try to acquire the dtm_mutex but recursive locking isn't
supported on mutex_lock().

[How]
Make the mutex_lock/unlock more fine grained and move them up such that
they're only required for the psp invocation itself.

Fixes: bf62221e9d0e ("drm/amd/display: Add DCN3.1 HDCP support")

Signed-off-by: Nicholas Kazlauskas 
Reviewed-by: Aric Cyr 
---
 drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c 
b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
index e9bd84ec027d..be61975f1470 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
@@ -105,6 +105,7 @@ static enum mod_hdcp_status remove_display_from_topology_v3(
dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE;
 
psp_dtm_invoke(psp, dtm_cmd->cmd_id);
+   mutex_unlock(>dtm_context.mutex);
 
if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) {
status = remove_display_from_topology_v2(hdcp, index);
@@ -115,8 +116,6 @@ static enum mod_hdcp_status remove_display_from_topology_v3(
HDCP_TOP_REMOVE_DISPLAY_TRACE(hdcp, display->index);
}
 
-   mutex_unlock(>dtm_context.mutex);
-
return status;
 }
 
@@ -205,6 +204,7 @@ static enum mod_hdcp_status add_display_to_topology_v3(
dtm_cmd->dtm_in_message.topology_update_v3.link_hdcp_cap = 
link->hdcp_supported_informational;
 
psp_dtm_invoke(psp, dtm_cmd->cmd_id);
+   mutex_unlock(>dtm_context.mutex);
 
if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) {
status = add_display_to_topology_v2(hdcp, display);
@@ -214,8 +214,6 @@ static enum mod_hdcp_status add_display_to_topology_v3(
HDCP_TOP_ADD_DISPLAY_TRACE(hdcp, display->index);
}
 
-   mutex_unlock(>dtm_context.mutex);
-
return status;
 }
 
-- 
2.25.1



[PATCH 0/5] Fix USBC lightup on DCN31B

2021-10-25 Thread Nicholas Kazlauskas
This patchset is a mini-promotion to fix USBC lightup
on DCN31B for both SST and MST displays.

There are five issues at play here:
1. Invalid clock table causing mode validation to fail
2. HDCP downgrade to v2 causes deadlock
3. MST payload allocation not being propagated
4. PHY mux selection not being properly indicated to DMCUB
5. Hang occuring during HPD on PHYF/G.

Jude Shih (2):
  drm/amd/display: Fix USB4 hot plug crash issue
  drm/amd/display: Enable dpia in dmub only for DCN31 B0

Meenakshikumar Somasundaram (1):
  drm/amd/display: MST support for DPIA

Michael Strauss (1):
  drm/amd/display: Fallback to clocks which meet requested voltage on
DCN31

Nicholas Kazlauskas (1):
  drm/amd/display: Fix deadlock when falling back to v2 from v3

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 35 +---
 .../display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c  | 13 +++--
 drivers/gpu/drm/amd/display/dc/core/dc.c  | 54 +++
 drivers/gpu/drm/amd/display/dc/core/dc_link.c | 28 ++
 drivers/gpu/drm/amd/display/dc/dc.h   |  6 +++
 drivers/gpu/drm/amd/display/dmub/dmub_srv.h   |  1 +
 .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   | 23 
 .../gpu/drm/amd/display/dmub/src/dmub_dcn31.c |  1 +
 .../drm/amd/display/modules/hdcp/hdcp_psp.c   |  6 +--
 9 files changed, 153 insertions(+), 14 deletions(-)

-- 
2.25.1



[PATCH] drm/amd/display: Fix surface optimization regression on Carrizo

2021-10-12 Thread Nicholas Kazlauskas
[Why]
DCE legacy optimization path isn't well tested under new DC optimization
flow which can result in underflow occuring when initializing X11 on
Carrizo.

[How]
Retain the legacy optimization flow for DCE and keep the new one for DCN
to satisfy optimizations being correctly applied for ASIC that can
support it.

Fixes: ab37c6527bb1 ("drm/amd/display: Optimize bandwidth on following fast 
update")
Cc: Bhawanpreet Lakha 
Cc: Mikita Lipski 
Reported-by: Tom St Denis 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/core/dc.c | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index da942e9f5142..f9876e429f26 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3118,8 +3118,13 @@ void dc_commit_updates_for_stream(struct dc *dc,
if (new_pipe->plane_state && new_pipe->plane_state != 
old_pipe->plane_state)
new_pipe->plane_state->force_full_update = true;
}
-   } else if (update_type == UPDATE_TYPE_FAST) {
-   /* Previous frame finished and HW is ready for optimization. */
+   } else if (update_type == UPDATE_TYPE_FAST && dc_ctx->dce_version >= 
DCE_VERSION_MAX) {
+   /*
+* Previous frame finished and HW is ready for optimization.
+*
+* Only relevant for DCN behavior where we can guarantee the 
optimization
+* is safe to apply - retain the legacy behavior for DCE.
+*/
dc_post_update_surfaces_to_stream(dc);
}
 
@@ -3178,6 +3183,12 @@ void dc_commit_updates_for_stream(struct dc *dc,
}
}
 
+   /* Legacy optimization path for DCE. */
+   if (update_type >= UPDATE_TYPE_FULL && dc_ctx->dce_version < 
DCE_VERSION_MAX) {
+   dc_post_update_surfaces_to_stream(dc);
+   TRACE_DCE_CLOCK_STATE(>bw_ctx.bw.dce);
+   }
+
return;
 
 }
-- 
2.25.1



[PATCH] drm/amd/display: Enable PSR by default on DCN3.1

2021-10-08 Thread Nicholas Kazlauskas
[Why]
New idle optimizations for DCN3.1 require PSR for optimal power savings
on panels that support it.

This was previously left disabled by default because of issues with
compositors that do not pageflip and scan out directly to the
frontbuffer.

For these compositors we now have detection methods that wait for x
number of pageflips after a full update - triggered by a buffer or
format change typically.

This may introduce bugs or new cases not tested by users so this is
only currently targeting DCN31.

[How]
Add code in DM to set PSR state by default for DCN3.1 while falling
back to the feature mask for older DCN.

Add a global debug flag that can be set to disable it for either.

Cc: Harry Wentland 
Cc: Roman Li 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c   | 17 -
 drivers/gpu/drm/amd/include/amd_shared.h|  5 +++--
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index dc595ecec595..ff545503a6ed 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4031,6 +4031,7 @@ static int amdgpu_dm_initialize_drm_device(struct 
amdgpu_device *adev)
int32_t primary_planes;
enum dc_connection_type new_connection_type = dc_connection_none;
const struct dc_plane_cap *plane;
+   bool psr_feature_enabled = false;
 
dm->display_indexes_num = dm->dc->caps.max_streams;
/* Update the actual used number of crtc */
@@ -4113,6 +4114,19 @@ static int amdgpu_dm_initialize_drm_device(struct 
amdgpu_device *adev)
DRM_DEBUG_KMS("Unsupported DCN IP version for outbox: 0x%X\n",
  adev->ip_versions[DCE_HWIP][0]);
}
+
+   /* Determine whether to enable PSR support by default. */
+   if (!(amdgpu_dc_debug_mask & DC_DISABLE_PSR)) {
+   switch (adev->ip_versions[DCE_HWIP][0]) {
+   case IP_VERSION(3, 1, 2):
+   case IP_VERSION(3, 1, 3):
+   psr_feature_enabled = true;
+   break;
+   default:
+   psr_feature_enabled = amdgpu_dc_feature_mask & 
DC_PSR_MASK;
+   break;
+   }
+   }
 #endif
 
/* loops over all connectors on the board */
@@ -4156,7 +4170,8 @@ static int amdgpu_dm_initialize_drm_device(struct 
amdgpu_device *adev)
} else if (dc_link_detect(link, DETECT_REASON_BOOT)) {
amdgpu_dm_update_connector_after_detect(aconnector);
register_backlight_device(dm, link);
-   if (amdgpu_dc_feature_mask & DC_PSR_MASK)
+
+   if (psr_feature_enabled)
amdgpu_dm_set_psr_caps(link);
}
 
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h 
b/drivers/gpu/drm/amd/include/amd_shared.h
index 257f280d3d53..f1a46d16f7ea 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -228,7 +228,7 @@ enum DC_FEATURE_MASK {
DC_FBC_MASK = (1 << 0), //0x1, disabled by default
DC_MULTI_MON_PP_MCLK_SWITCH_MASK = (1 << 1), //0x2, enabled by default
DC_DISABLE_FRACTIONAL_PWM_MASK = (1 << 2), //0x4, disabled by default
-   DC_PSR_MASK = (1 << 3), //0x8, disabled by default
+   DC_PSR_MASK = (1 << 3), //0x8, disabled by default for dcn < 3.1
DC_EDP_NO_POWER_SEQUENCING = (1 << 4), //0x10, disabled by default
 };
 
@@ -236,7 +236,8 @@ enum DC_DEBUG_MASK {
DC_DISABLE_PIPE_SPLIT = 0x1,
DC_DISABLE_STUTTER = 0x2,
DC_DISABLE_DSC = 0x4,
-   DC_DISABLE_CLOCK_GATING = 0x8
+   DC_DISABLE_CLOCK_GATING = 0x8,
+   DC_DISABLE_PSR = 0x10,
 };
 
 enum amd_dpm_forced_level;
-- 
2.25.1



[PATCH] drm/amd/display: Fix white screen page fault for gpuvm

2021-09-13 Thread Nicholas Kazlauskas
[Why]
The "base_addr_is_mc_addr" field was added for dcn3.1 support but
pa_config was never updated to set it to false.

Uninitialized memory causes it to be set to true which results in
address mistranslation and white screen.

[How]
Use memset to ensure all fields are initialized to 0 by default.

Cc: Aaron Liu 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 53363728dbb..b0426bb3f2e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1125,6 +1125,8 @@ static void mmhub_read_system_context(struct 
amdgpu_device *adev, struct dc_phy_
uint32_t agp_base, agp_bot, agp_top;
PHYSICAL_ADDRESS_LOC page_table_start, page_table_end, page_table_base;
 
+   memset(pa_config, 0, sizeof(*pa_config));
+
logical_addr_low  = min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18;
pt_base = amdgpu_gmc_pd_addr(adev->gart.bo);
 
-- 
2.25.1



[PATCH] drm/amd/display: Add NULL checks for vblank workqueue

2021-09-07 Thread Nicholas Kazlauskas
[Why]
If we're running a headless config with 0 links then the vblank
workqueue will be NULL - causing a NULL pointer exception during
any commit.

[How]
Guard access to the workqueue if it's NULL and don't queue or flush
work if it is.

Cc: Roman Li 
Cc: Wayne Lin 
Cc: Harry Wentland 
Reported-by: Mike Lothian 
BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1700
Fixes: 91f86d4cce2 ("drm/amd/display: Use vblank control events for PSR 
enable/disable")
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 32 +++
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 8837259215d..46e08736f94 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6185,21 +6185,23 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, 
bool enable)
return 0;
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-   work = kzalloc(sizeof(*work), GFP_ATOMIC);
-   if (!work)
-   return -ENOMEM;
+   if (dm->vblank_control_workqueue) {
+   work = kzalloc(sizeof(*work), GFP_ATOMIC);
+   if (!work)
+   return -ENOMEM;
 
-   INIT_WORK(>work, vblank_control_worker);
-   work->dm = dm;
-   work->acrtc = acrtc;
-   work->enable = enable;
+   INIT_WORK(>work, vblank_control_worker);
+   work->dm = dm;
+   work->acrtc = acrtc;
+   work->enable = enable;
 
-   if (acrtc_state->stream) {
-   dc_stream_retain(acrtc_state->stream);
-   work->stream = acrtc_state->stream;
-   }
+   if (acrtc_state->stream) {
+   dc_stream_retain(acrtc_state->stream);
+   work->stream = acrtc_state->stream;
+   }
 
-   queue_work(dm->vblank_control_workqueue, >work);
+   queue_work(dm->vblank_control_workqueue, >work);
+   }
 #endif
 
return 0;
@@ -8809,7 +8811,8 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
 * If PSR or idle optimizations are enabled then flush out
 * any pending work before hardware programming.
 */
-   flush_workqueue(dm->vblank_control_workqueue);
+   if (dm->vblank_control_workqueue)
+   flush_workqueue(dm->vblank_control_workqueue);
 #endif
 
bundle->stream_update.stream = acrtc_state->stream;
@@ -9144,7 +9147,8 @@ static void amdgpu_dm_atomic_commit_tail(struct 
drm_atomic_state *state)
/* if there mode set or reset, disable eDP PSR */
if (mode_set_reset_required) {
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-   flush_workqueue(dm->vblank_control_workqueue);
+   if (dm->vblank_control_workqueue)
+   flush_workqueue(dm->vblank_control_workqueue);
 #endif
amdgpu_dm_psr_disable_all(dm);
}
-- 
2.25.1



[PATCH] drm/amd/display: Extend DMUB diagnostic logging to DCN3.1

2021-06-30 Thread Nicholas Kazlauskas
[Why & How]
Extend existing support for DCN2.1 DMUB diagnostic logging to
DCN3.1 so we can collect useful information if the DMUB hangs.

Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 60 +++
 .../gpu/drm/amd/display/dmub/src/dmub_dcn31.h | 16 -
 .../gpu/drm/amd/display/dmub/src/dmub_srv.c   |  5 +-
 3 files changed, 76 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c 
b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
index 8c886ece71..973de34641 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
@@ -352,3 +352,63 @@ uint32_t dmub_dcn31_get_current_time(struct dmub_srv *dmub)
 {
return REG_READ(DMCUB_TIMER_CURRENT);
 }
+
+void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct 
dmub_diagnostic_data *diag_data)
+{
+   uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset;
+   uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled;
+
+   if (!dmub || !diag_data)
+   return;
+
+   memset(diag_data, 0, sizeof(*diag_data));
+
+   diag_data->dmcub_version = dmub->fw_version;
+
+   diag_data->scratch[0] = REG_READ(DMCUB_SCRATCH0);
+   diag_data->scratch[1] = REG_READ(DMCUB_SCRATCH1);
+   diag_data->scratch[2] = REG_READ(DMCUB_SCRATCH2);
+   diag_data->scratch[3] = REG_READ(DMCUB_SCRATCH3);
+   diag_data->scratch[4] = REG_READ(DMCUB_SCRATCH4);
+   diag_data->scratch[5] = REG_READ(DMCUB_SCRATCH5);
+   diag_data->scratch[6] = REG_READ(DMCUB_SCRATCH6);
+   diag_data->scratch[7] = REG_READ(DMCUB_SCRATCH7);
+   diag_data->scratch[8] = REG_READ(DMCUB_SCRATCH8);
+   diag_data->scratch[9] = REG_READ(DMCUB_SCRATCH9);
+   diag_data->scratch[10] = REG_READ(DMCUB_SCRATCH10);
+   diag_data->scratch[11] = REG_READ(DMCUB_SCRATCH11);
+   diag_data->scratch[12] = REG_READ(DMCUB_SCRATCH12);
+   diag_data->scratch[13] = REG_READ(DMCUB_SCRATCH13);
+   diag_data->scratch[14] = REG_READ(DMCUB_SCRATCH14);
+   diag_data->scratch[15] = REG_READ(DMCUB_SCRATCH15);
+
+   diag_data->undefined_address_fault_addr = 
REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR);
+   diag_data->inst_fetch_fault_addr = 
REG_READ(DMCUB_INST_FETCH_FAULT_ADDR);
+   diag_data->data_write_fault_addr = 
REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR);
+
+   diag_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR);
+   diag_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR);
+   diag_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE);
+
+   diag_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR);
+   diag_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR);
+   diag_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE);
+
+   REG_GET(DMCUB_CNTL, DMCUB_ENABLE, _dmub_enabled);
+   diag_data->is_dmcub_enabled = is_dmub_enabled;
+
+   REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, _soft_reset);
+   diag_data->is_dmcub_soft_reset = is_soft_reset;
+
+   REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, _sec_reset);
+   diag_data->is_dmcub_secure_reset = is_sec_reset;
+
+   REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, _traceport_enabled);
+   diag_data->is_traceport_en  = is_traceport_enabled;
+
+   REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, 
_cw0_enabled);
+   diag_data->is_cw0_enabled = is_cw0_enabled;
+
+   REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, 
_cw6_enabled);
+   diag_data->is_cw6_enabled = is_cw6_enabled;
+}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h 
b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
index 2829c3e9a3..9456a6a2d5 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
@@ -36,6 +36,9 @@ struct dmub_srv;
DMUB_SR(DMCUB_CNTL) \
DMUB_SR(DMCUB_CNTL2) \
DMUB_SR(DMCUB_SEC_CNTL) \
+   DMUB_SR(DMCUB_INBOX0_SIZE) \
+   DMUB_SR(DMCUB_INBOX0_RPTR) \
+   DMUB_SR(DMCUB_INBOX0_WPTR) \
DMUB_SR(DMCUB_INBOX1_BASE_ADDRESS) \
DMUB_SR(DMCUB_INBOX1_SIZE) \
DMUB_SR(DMCUB_INBOX1_RPTR) \
@@ -103,11 +106,15 @@ struct dmub_srv;
DMUB_SR(DMCUB_SCRATCH14) \
DMUB_SR(DMCUB_SCRATCH15) \
DMUB_SR(DMCUB_GPINT_DATAIN1) \
+   DMUB_SR(DMCUB_GPINT_DATAOUT) \
DMUB_SR(CC_DC_PIPE_DIS) \
DMUB_SR(MMHUBBUB_SOFT_RESET) \
DMUB_SR(DCN_VM_FB_LOCATION_BASE) \
DMUB_SR(DCN_VM_FB_OFFSET) \
-   DMUB_SR(DMCUB_TIMER_CURRENT)
+   DMUB_SR(DMCUB_TIMER_CURRENT) \
+   DMUB_SR(DMCUB_INST_FETCH_FAULT_ADDR) \
+   DMUB_SR(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR) \
+   DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR)
 
 #define DMUB_DCN31_FIELDS() \
DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \
@@ -115,6 +122,7 @@ struct dmub_srv;
DMUB

[PATCH] drm/amd/display: Fix GPU scaling regression by FS video support

2021-05-19 Thread Nicholas Kazlauskas
[Why]
FS video support regressed GPU scaling and the scaled buffer ends up
stuck in the top left of the screen at native size - full, aspect,
center scaling modes do not function.

This is because decide_crtc_timing_for_drm_display_mode() does not
get called when scaling is enabled.

[How]
Split recalculate timing and scaling into two different flags.

We don't want to call drm_mode_set_crtcinfo() for scaling, but we
do want to call it for FS video.

Optimize and move preferred_refresh calculation next to
decide_crtc_timing_for_drm_display_mode() like it used to be since
that's not used for FS video.

We don't need to copy over the VIC or polarity in the case of FS video
modes because those don't change.

Fixes: a372f4abec ("drm/amd/display: Skip modeset for front porch change")

Cc: Aurabindo Pillai 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 8cd270f129..759621b0e8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5672,7 +5672,8 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
struct drm_display_mode saved_mode;
struct drm_display_mode *freesync_mode = NULL;
bool native_mode_found = false;
-   bool recalculate_timing = dm_state ? (dm_state->scaling != RMX_OFF) : 
false;
+   bool recalculate_timing = false;
+   bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false;
int mode_refresh;
int preferred_refresh = 0;
 #if defined(CONFIG_DRM_AMD_DC_DCN)
@@ -5735,7 +5736,7 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
 */
DRM_DEBUG_DRIVER("No preferred mode found\n");
} else {
-   recalculate_timing |= amdgpu_freesync_vid_mode &&
+   recalculate_timing = amdgpu_freesync_vid_mode &&
 is_freesync_video_mode(, aconnector);
if (recalculate_timing) {
freesync_mode = 
get_highest_refresh_rate_mode(aconnector, false);
@@ -5743,11 +5744,10 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
mode = *freesync_mode;
} else {
decide_crtc_timing_for_drm_display_mode(
-   , preferred_mode,
-   dm_state ? (dm_state->scaling != RMX_OFF) : 
false);
-   }
+   , preferred_mode, scale);
 
-   preferred_refresh = drm_mode_vrefresh(preferred_mode);
+   preferred_refresh = drm_mode_vrefresh(preferred_mode);
+   }
}
 
if (recalculate_timing)
@@ -5759,7 +5759,7 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
* If scaling is enabled and refresh rate didn't change
* we copy the vic and polarities of the old timings
*/
-   if (!recalculate_timing || mode_refresh != preferred_refresh)
+   if (!scale || mode_refresh != preferred_refresh)
fill_stream_properties_from_drm_display_mode(
stream, , >base, con_state, NULL,
requested_bpc);
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH] drm/amd/powerplay: Fix hardmins not being sent to SMU for RV

2020-08-21 Thread Nicholas Kazlauskas
[Why]
DC uses these to raise the voltage as needed for higher dispclk/dppclk
and to ensure that we have enough bandwidth to drive the displays.

There's a bug preventing these from actuially sending messages since
it's checking the actual clock (which is 0) instead of the incoming
clock (which shouldn't be 0) when deciding to send the hardmin.

[How]
Check the clocks != 0 instead of the actual clocks.

Fixes: 9ed9203c3ee7 ("drm/amd/powerplay: rv dal-pplib interface refactor 
powerplay part")
Cc: Hersen Wu 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c 
b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c
index c9cfe90a2947..9ee8cf8267c8 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c
@@ -204,8 +204,7 @@ static int smu10_set_min_deep_sleep_dcefclk(struct pp_hwmgr 
*hwmgr, uint32_t clo
 {
struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 
-   if (smu10_data->need_min_deep_sleep_dcefclk &&
-   smu10_data->deep_sleep_dcefclk != clock) {
+   if (clock && smu10_data->deep_sleep_dcefclk != clock) {
smu10_data->deep_sleep_dcefclk = clock;
smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetMinDeepSleepDcefclk,
@@ -219,8 +218,7 @@ static int smu10_set_hard_min_dcefclk_by_freq(struct 
pp_hwmgr *hwmgr, uint32_t c
 {
struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 
-   if (smu10_data->dcf_actual_hard_min_freq &&
-   smu10_data->dcf_actual_hard_min_freq != clock) {
+   if (clock && smu10_data->dcf_actual_hard_min_freq != clock) {
smu10_data->dcf_actual_hard_min_freq = clock;
smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetHardMinDcefclkByFreq,
@@ -234,8 +232,7 @@ static int smu10_set_hard_min_fclk_by_freq(struct pp_hwmgr 
*hwmgr, uint32_t cloc
 {
struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 
-   if (smu10_data->f_actual_hard_min_freq &&
-   smu10_data->f_actual_hard_min_freq != clock) {
+   if (clock && smu10_data->f_actual_hard_min_freq != clock) {
smu10_data->f_actual_hard_min_freq = clock;
smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetHardMinFclkByFreq,
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH] drm/amd/display: Reject overlay plane configurations in multi-display scenarios

2020-08-19 Thread Nicholas Kazlauskas
[Why]
These aren't stable on some platform configurations when driving
multiple displays, especially on higher resolution.

In particular the delay in asserting p-state and validating from
x86 outweights any power or performance benefit from the hardware
composition.

Under some configurations this will manifest itself as extreme stutter
or unresponsiveness especially when combined with cursor movement.

[How]
Disable these for now. Exposing overlays to userspace doesn't guarantee
that they'll be able to use them in any and all configurations and it's
part of the DRM contract to have userspace gracefully handle validation
failures when they occur.

Valdiation occurs as part of DC and this in particular affects RV, so
disable this in dcn10_global_validation.

Cc: Hersen Wu 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
index 07571f84e0f8..1abd81e17f09 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
@@ -1213,6 +1213,7 @@ static enum dc_status dcn10_validate_global(struct dc 
*dc, struct dc_state *cont
bool video_large = false;
bool desktop_large = false;
bool dcc_disabled = false;
+   bool mpo_enabled = false;
 
for (i = 0; i < context->stream_count; i++) {
if (context->stream_status[i].plane_count == 0)
@@ -1221,6 +1222,9 @@ static enum dc_status dcn10_validate_global(struct dc 
*dc, struct dc_state *cont
if (context->stream_status[i].plane_count > 2)
return DC_FAIL_UNSUPPORTED_1;
 
+   if (context->stream_status[i].plane_count > 1)
+   mpo_enabled = true;
+
for (j = 0; j < context->stream_status[i].plane_count; j++) {
struct dc_plane_state *plane =
context->stream_status[i].plane_states[j];
@@ -1244,6 +1248,10 @@ static enum dc_status dcn10_validate_global(struct dc 
*dc, struct dc_state *cont
}
}
 
+   /* Disable MPO in multi-display configurations. */
+   if (context->stream_count > 1 && mpo_enabled)
+   return DC_FAIL_UNSUPPORTED_1;
+
/*
 * Workaround: On DCN10 there is UMC issue that causes underflow when
 * playing 4k video on 4k desktop with video downscaled and single 
channel
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH v2] drm/amd/display: Replace DRM private objects with subclassed DRM atomic state

2020-08-14 Thread Nicholas Kazlauskas
[Why]
DM atomic check was structured in a way that we required old DC state
in order to dynamically add and remove planes and streams from the
context to build the DC state context for validation.

DRM private objects were used to carry over the last DC state and
were added to the context on nearly every commit - regardless of fast
or full so we could check whether or not the new state could affect
bandwidth.

The problem with this model is that DRM private objects do not
implicitly stall out other commits.

So if you have two commits touching separate DRM objects they could
run concurrently and potentially execute out of order - leading to a
use-after-free.

If we want this to be safe we have two options:
1. Stall out concurrent commits since they touch the same private object
2. Refactor DM to not require old DC state and drop private object usage

[How]
This implements approach #2 since it still allows for judder free
updates in multi-display scenarios.

I'll list the big changes in order at a high level:

1. Subclass DRM atomic state instead of using DRM private objects.

DC relied on the old state to determine which changes cause bandwidth
updates but now we have DM perform similar checks based on DRM state
instead - dropping the requirement for old state to exist at all.

This means that we can now build a new DC context from scratch whenever
we have something that DM thinks could affect bandwidth.

Whenever we need to rebuild bandwidth we now add all CRTCs and planes
to the DRM state in order to get the absolute set of DC streams and
DC planes.

This introduces a stall on other commits, but this stall already
exists because of the lock_and_validation logic and it's necessary
since updates may move around pipes and require full reprogramming.

2. Drop workarounds to add planes to maintain z-order early in atomic
check. This is no longer needed because of the changes for (1).

This also involves fixing up should_plane_reset checks since we can just
avoid resetting streams and planes when they haven't actually changed.

3. Rework dm_update_crtc_state and dm_update_plane_state to be single
pass instead of two pass.

This is necessary since we no longer have the dc_state to add and
remove planes to the context in and we want to defer creation to the
end of commit_check.

It also makes the logic a lot simpler to follow since as an added bonus.

v2: rebase, naming, comments and spelling fixes

Cc: Rodrigo Siqueira 
Cc: Bhawanpreet Lakha 
Cc: Harry Wentland 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 700 +++---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  11 +-
 2 files changed, 279 insertions(+), 432 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index ff5f7f7ceec6..d76927bac737 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1839,7 +1839,6 @@ static int dm_resume(void *handle)
struct drm_plane *plane;
struct drm_plane_state *new_plane_state;
struct dm_plane_state *dm_new_plane_state;
-   struct dm_atomic_state *dm_state = 
to_dm_atomic_state(dm->atomic_obj.state);
enum dc_connection_type new_connection_type = dc_connection_none;
struct dc_state *dc_state;
int i, r, j;
@@ -1879,11 +1878,6 @@ static int dm_resume(void *handle)
 
return 0;
}
-   /* Recreate dc_state - DC invalidates it when setting power state to 
S3. */
-   dc_release_state(dm_state->context);
-   dm_state->context = dc_create_state(dm->dc);
-   /* TODO: Remove dc_state->dccg, use dc->dccg directly. */
-   dc_resource_state_construct(dm->dc, dm_state->context);
 
/* Before powering on DC we need to re-initialize DMUB. */
r = dm_dmub_hw_init(adev);
@@ -2019,11 +2013,52 @@ const struct amdgpu_ip_block_version dm_ip_block =
  * *WIP*
  */
 
+static struct drm_atomic_state *
+amdgpu_dm_atomic_state_alloc(struct drm_device *dev)
+{
+   struct dm_atomic_state *dm_state;
+
+   dm_state = kzalloc(sizeof(*dm_state), GFP_KERNEL);
+
+   if (!dm_state)
+   return NULL;
+
+   if (drm_atomic_state_init(dev, _state->base) < 0) {
+   kfree(dm_state);
+   return NULL;
+   }
+
+   return _state->base;
+}
+
+static void amdgpu_dm_atomic_state_free(struct drm_atomic_state *state)
+{
+   struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
+
+   if (dm_state->context) {
+   dc_release_state(dm_state->context);
+   dm_state->context = NULL;
+   }
+
+   drm_atomic_state_default_release(state);
+   kfree(state);
+}
+
+static void amdgpu_dm_atomic_state_clear(struct drm_atomic_state *state)
+{
+   struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
+
+   d

[PATCH 4/7] drm/amd/display: Use validated tiling_flags and tmz_surface in commit_tail

2020-07-30 Thread Nicholas Kazlauskas
[Why]
So we're not racing with userspace or deadlocking DM.

[How]
These flags are now stored on dm_plane_state itself and acquried and
validated during commit_check, so just use those instead.

Cc: Daniel Vetter 
Cc: Bhawanpreet Lakha 
Cc: Rodrigo Siqueira 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  | 18 --
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f78c09c9585e..0d5f45742bb5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7094,8 +7094,6 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
long r;
unsigned long flags;
struct amdgpu_bo *abo;
-   uint64_t tiling_flags;
-   bool tmz_surface = false;
uint32_t target_vblank, last_flip_vblank;
bool vrr_active = amdgpu_dm_vrr_active(acrtc_state);
bool pflip_present = false;
@@ -7179,20 +7177,12 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
if (unlikely(r <= 0))
DRM_ERROR("Waiting for fences timed out!");
 
-   /*
-* We cannot reserve buffers here, which means the normal flag
-* access functions don't work. Paper over this with READ_ONCE,
-* but maybe the flags are invariant enough that not even that
-* would be needed.
-*/
-   tiling_flags = READ_ONCE(abo->tiling_flags);
-   tmz_surface = READ_ONCE(abo->flags) & 
AMDGPU_GEM_CREATE_ENCRYPTED;
-
fill_dc_plane_info_and_addr(
-   dm->adev, new_plane_state, tiling_flags,
+   dm->adev, new_plane_state,
+   dm_new_plane_state->tiling_flags,
>plane_infos[planes_count],
-   >flip_addrs[planes_count].address, tmz_surface,
-   false);
+   >flip_addrs[planes_count].address,
+   dm_new_plane_state->tmz_surface, false);
 
DRM_DEBUG_DRIVER("plane: id=%d dcc_en=%d\n",
 new_plane_state->plane->index,
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 2/7] drm/amd/display: Reset plane when tiling flags change

2020-07-30 Thread Nicholas Kazlauskas
[Why]
Enabling or disable DCC or switching between tiled and linear formats
can require bandwidth updates.

They're currently skipping all DC validation by being treated as purely
surface updates.

[How]
Treat tiling_flag changes (which encode DCC state) as a condition for
resetting the plane.

Cc: Bhawanpreet Lakha 
Cc: Rodrigo Siqueira 
Cc: Hersen Wu 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 7cc5ab90ce13..bf1881bd492c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8332,6 +8332,8 @@ static bool should_reset_plane(struct drm_atomic_state 
*state,
 * TODO: Come up with a more elegant solution for this.
 */
for_each_oldnew_plane_in_state(state, other, old_other_state, 
new_other_state, i) {
+   struct dm_plane_state *old_dm_plane_state, *new_dm_plane_state;
+
if (other->type == DRM_PLANE_TYPE_CURSOR)
continue;
 
@@ -8342,9 +8344,20 @@ static bool should_reset_plane(struct drm_atomic_state 
*state,
if (old_other_state->crtc != new_other_state->crtc)
return true;
 
-   /* TODO: Remove this once we can handle fast format changes. */
-   if (old_other_state->fb && new_other_state->fb &&
-   old_other_state->fb->format != new_other_state->fb->format)
+   /* Framebuffer checks fall at the end. */
+   if (!old_other_state->fb || !new_other_state->fb)
+   continue;
+
+   /* Pixel format changes can require bandwidth updates. */
+   if (old_other_state->fb->format != new_other_state->fb->format)
+   return true;
+
+   old_dm_plane_state = to_dm_plane_state(old_other_state);
+   new_dm_plane_state = to_dm_plane_state(new_other_state);
+
+   /* Tiling and DCC changes also require bandwidth updates. */
+   if (old_dm_plane_state->tiling_flags !=
+   new_dm_plane_state->tiling_flags)
return true;
}
 
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 3/7] drm/amd/display: Avoid using unvalidated tiling_flags and tmz_surface in prepare_planes

2020-07-30 Thread Nicholas Kazlauskas
[Why]
We're racing with userspace as the flags could potentially change
from when we acquired and validated them in commit_check.

[How]
We unfortunately can't drop this function in its entirety from
prepare_planes since we don't know the afb->address at commit_check
time yet.

So instead of querying new tiling_flags and tmz_surface use the ones
from the plane_state directly.

While we're at it, also update the force_disable_dcc option based
on the state from atomic check.

Cc: Bhawanpreet Lakha 
Cc: Rodrigo Siqueira 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 ++-
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index bf1881bd492c..f78c09c9585e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5794,14 +5794,8 @@ static int dm_plane_helper_prepare_fb(struct drm_plane 
*plane,
struct list_head list;
struct ttm_validate_buffer tv;
struct ww_acquire_ctx ticket;
-   uint64_t tiling_flags;
uint32_t domain;
int r;
-   bool tmz_surface = false;
-   bool force_disable_dcc = false;
-
-   dm_plane_state_old = to_dm_plane_state(plane->state);
-   dm_plane_state_new = to_dm_plane_state(new_state);
 
if (!new_state->fb) {
DRM_DEBUG_DRIVER("No FB bound\n");
@@ -5845,27 +5839,35 @@ static int dm_plane_helper_prepare_fb(struct drm_plane 
*plane,
return r;
}
 
-   amdgpu_bo_get_tiling_flags(rbo, _flags);
-
-   tmz_surface = amdgpu_bo_encrypted(rbo);
-
ttm_eu_backoff_reservation(, );
 
afb->address = amdgpu_bo_gpu_offset(rbo);
 
amdgpu_bo_ref(rbo);
 
+   /**
+* We don't do surface updates on planes that have been newly created,
+* but we also don't have the afb->address during atomic check.
+*
+* Fill in buffer attributes depending on the address here, but only on
+* newly created planes since they're not being used by DC yet and this
+* won't modify global state.
+*/
+   dm_plane_state_old = to_dm_plane_state(plane->state);
+   dm_plane_state_new = to_dm_plane_state(new_state);
+
if (dm_plane_state_new->dc_state &&
-   dm_plane_state_old->dc_state != 
dm_plane_state_new->dc_state) {
-   struct dc_plane_state *plane_state = 
dm_plane_state_new->dc_state;
+   dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) {
+   struct dc_plane_state *plane_state =
+   dm_plane_state_new->dc_state;
+   bool force_disable_dcc = !plane_state->dcc.enable;
 
-   force_disable_dcc = adev->asic_type == CHIP_RAVEN && 
adev->in_suspend;
fill_plane_buffer_attributes(
adev, afb, plane_state->format, plane_state->rotation,
-   tiling_flags, _state->tiling_info,
-   _state->plane_size, _state->dcc,
-   _state->address, tmz_surface,
-   force_disable_dcc);
+   dm_plane_state_new->tiling_flags,
+   _state->tiling_info, _state->plane_size,
+   _state->dcc, _state->address,
+   dm_plane_state_new->tmz_surface, force_disable_dcc);
}
 
return 0;
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 5/7] drm/amd/display: Reset plane for anything that's not a FAST update

2020-07-30 Thread Nicholas Kazlauskas
[Why]
MEDIUM or FULL updates can require global validation or affect
bandwidth. By treating these all simply as surface updates we aren't
actually passing this through DC global validation.

[How]
There's currently no way to pass surface updates through DC global
validation, nor do I think it's a good idea to change the interface
to accept these.

DC global validation itself is currently stateless, and we can move
our update type checking to be stateless as well by duplicating DC
surface checks in DM based on DRM properties.

We wanted to rely on DC automatically determining this since DC knows
best, but DM is ultimately what fills in everything into DC plane
state so it does need to know as well.

There are basically only three paths that we exercise in DM today:

1) Cursor (async update)
2) Pageflip (fast update)
3) Full pipe programming (medium/full updates)

Which means that anything that's more than a pageflip really needs to
go down path #3.

So this change duplicates all the surface update checks based on DRM
state instead inside of should_reset_plane().

Next step is dropping dm_determine_update_type_for_commit and we no
longer require the old DC state at all for global validation.

Optimization can come later so we don't reset DC planes at all for
MEDIUM udpates and avoid validation, but we might require some extra
checks in DM to achieve this.

Cc: Bhawanpreet Lakha 
Cc: Hersen Wu 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 +++
 1 file changed, 25 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0d5f45742bb5..2cbb29199e61 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8336,6 +8336,31 @@ static bool should_reset_plane(struct drm_atomic_state 
*state,
if (old_other_state->crtc != new_other_state->crtc)
return true;
 
+   /* Src/dst size and scaling updates. */
+   if (old_other_state->src_w != new_other_state->src_w ||
+   old_other_state->src_h != new_other_state->src_h ||
+   old_other_state->crtc_w != new_other_state->crtc_w ||
+   old_other_state->crtc_h != new_other_state->crtc_h)
+   return true;
+
+   /* Rotation / mirroring updates. */
+   if (old_other_state->rotation != new_other_state->rotation)
+   return true;
+
+   /* Blending updates. */
+   if (old_other_state->pixel_blend_mode !=
+   new_other_state->pixel_blend_mode)
+   return true;
+
+   /* Alpha updates. */
+   if (old_other_state->alpha != new_other_state->alpha)
+   return true;
+
+   /* Colorspace changes. */
+   if (old_other_state->color_range != 
new_other_state->color_range ||
+   old_other_state->color_encoding != 
new_other_state->color_encoding)
+   return true;
+
/* Framebuffer checks fall at the end. */
if (!old_other_state->fb || !new_other_state->fb)
continue;
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 1/7] drm/amd/display: Store tiling_flags and tmz_surface on dm_plane_state

2020-07-30 Thread Nicholas Kazlauskas
[Why]
Store these in advance so we can reuse them later in commit_tail without
having to reserve the fbo again.

These will also be used for checking for tiling changes when deciding
to reset the plane or not.

[How]
This change should mostly be a refactor. Only commit check is affected
for now and I'll drop the get_fb_info calls in prepare_planes and
commit_tail after.

This runs a prepass loop once we think that all planes have been added
to the context and replaces the get_fb_info calls with accessing the
dm_plane_state instead.

Cc: Bhawanpreet Lakha 
Cc: Rodrigo Siqueira 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 60 +++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  2 +
 2 files changed, 37 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 8d64f5fde7e2..7cc5ab90ce13 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3700,8 +3700,17 @@ static int fill_dc_scaling_info(const struct 
drm_plane_state *state,
 static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb,
   uint64_t *tiling_flags, bool *tmz_surface)
 {
-   struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->base.obj[0]);
-   int r = amdgpu_bo_reserve(rbo, false);
+   struct amdgpu_bo *rbo;
+   int r;
+
+   if (!amdgpu_fb) {
+   *tiling_flags = 0;
+   *tmz_surface = false;
+   return 0;
+   }
+
+   rbo = gem_to_amdgpu_bo(amdgpu_fb->base.obj[0]);
+   r = amdgpu_bo_reserve(rbo, false);
 
if (unlikely(r)) {
/* Don't show error message when returning -ERESTARTSYS */
@@ -4124,13 +4133,10 @@ static int fill_dc_plane_attributes(struct 
amdgpu_device *adev,
struct drm_crtc_state *crtc_state)
 {
struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
-   const struct amdgpu_framebuffer *amdgpu_fb =
-   to_amdgpu_framebuffer(plane_state->fb);
+   struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
struct dc_scaling_info scaling_info;
struct dc_plane_info plane_info;
-   uint64_t tiling_flags;
int ret;
-   bool tmz_surface = false;
bool force_disable_dcc = false;
 
ret = fill_dc_scaling_info(plane_state, _info);
@@ -4142,15 +4148,12 @@ static int fill_dc_plane_attributes(struct 
amdgpu_device *adev,
dc_plane_state->clip_rect = scaling_info.clip_rect;
dc_plane_state->scaling_quality = scaling_info.scaling_quality;
 
-   ret = get_fb_info(amdgpu_fb, _flags, _surface);
-   if (ret)
-   return ret;
-
force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend;
-   ret = fill_dc_plane_info_and_addr(adev, plane_state, tiling_flags,
+   ret = fill_dc_plane_info_and_addr(adev, plane_state,
+ dm_plane_state->tiling_flags,
  _info,
  _plane_state->address,
- tmz_surface,
+ dm_plane_state->tmz_surface,
  force_disable_dcc);
if (ret)
return ret;
@@ -5753,6 +5756,10 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
dc_plane_state_retain(dm_plane_state->dc_state);
}
 
+   /* Framebuffer hasn't been updated yet, so retain old flags. */
+   dm_plane_state->tiling_flags = old_dm_plane_state->tiling_flags;
+   dm_plane_state->tmz_surface = old_dm_plane_state->tmz_surface;
+
return _plane_state->base;
 }
 
@@ -8557,13 +8564,9 @@ dm_determine_update_type_for_commit(struct 
amdgpu_display_manager *dm,
continue;
 
for_each_oldnew_plane_in_state(state, plane, old_plane_state, 
new_plane_state, j) {
-   const struct amdgpu_framebuffer *amdgpu_fb =
-   to_amdgpu_framebuffer(new_plane_state->fb);
struct dc_plane_info *plane_info = 
>plane_infos[num_plane];
struct dc_flip_addrs *flip_addr = 
>flip_addrs[num_plane];
struct dc_scaling_info *scaling_info = 
>scaling_infos[num_plane];
-   uint64_t tiling_flags;
-   bool tmz_surface = false;
 
new_plane_crtc = new_plane_state->crtc;
new_dm_plane_state = to_dm_plane_state(new_plane_state);
@@ -8610,16 +8613,12 @@ dm_determine_update_type_for_commit(struct 
amdgpu_display_manager *dm,
 
bundle->surface_updates[num_pl

[PATCH 7/7] drm/amd/display: Replace DRM private objects with subclassed DRM atomic state

2020-07-30 Thread Nicholas Kazlauskas
[Why]
DM atomic check was structured in a way that we required old DC state
in order to dynamically add and remove planes and streams from the
context to build the DC state context for validation.

DRM private objects were used to carry over the last DC state and
were added to the context on nearly every commit - regardless of fast
or full so we could check whether or not the new state could affect
bandwidth.

The problem with this model is that DRM private objects do not
implicitly stall out other commits.

So if you have two commits touching separate DRM objects they could
run concurrently and potentially execute out of order - leading to a
use-after-free.

If we want this to be safe we have two options:
1. Stall out concurrent commits since they touch the same private object
2. Refactor DM to not require old DC state and drop private object usage

[How]
This implements approach #2 since it still allows for judder free
updates in multi-display scenarios.

I'll list the big changes in order at a high level:

1. Subclass DRM atomic state instead of using DRM private objects.

DC relied on the old state to determine which changes cause bandwidth
updates but now we have DM perform similar checks based on DRM state
instead - dropping the requirement for old state to exist at all.

This means that we can now build a new DC context from scratch whenever
we have something that DM thinks could affect bandwidth.

Whenever we need to rebuild bandwidth we now add all CRTCs and planes
to the DRM state in order to get the absolute set of DC streams and
DC planes.

This introduces a stall on other commits, but this stall already
exists because of the lock_and_validation logic and it's necessary
since updates may move around pipes and require full reprogramming.

2. Drop workarounds to add planes to maintain z-order early in atomic
check. This is no longer needed because of the changes for (1).

This also involves fixing up should_plane_reset checks since we can just
avoid resetting streams and planes when they haven't actually changed.

3. Rework dm_update_crtc_state and dm_update_plane_state to be single
pass instead of two pass.

This is necessary since we no longer have the dc_state to add and
remove planes to the context in and we want to defer creation to the
end of commit_check.

It also makes the logic a lot simpler to follow since as an added bonus.

Cc: Bhawanpreet Lakha 
Cc: Harry Wentland 
Cc: Leo Li 
Cc: Daniel Vetter 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 720 +++---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  11 +-
 2 files changed, 280 insertions(+), 451 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 59829ec81694..97a7dfc620e8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1839,7 +1839,6 @@ static int dm_resume(void *handle)
struct drm_plane *plane;
struct drm_plane_state *new_plane_state;
struct dm_plane_state *dm_new_plane_state;
-   struct dm_atomic_state *dm_state = 
to_dm_atomic_state(dm->atomic_obj.state);
enum dc_connection_type new_connection_type = dc_connection_none;
struct dc_state *dc_state;
int i, r, j;
@@ -1879,11 +1878,6 @@ static int dm_resume(void *handle)
 
return 0;
}
-   /* Recreate dc_state - DC invalidates it when setting power state to 
S3. */
-   dc_release_state(dm_state->context);
-   dm_state->context = dc_create_state(dm->dc);
-   /* TODO: Remove dc_state->dccg, use dc->dccg directly. */
-   dc_resource_state_construct(dm->dc, dm_state->context);
 
/* Before powering on DC we need to re-initialize DMUB. */
r = dm_dmub_hw_init(adev);
@@ -2019,11 +2013,51 @@ const struct amdgpu_ip_block_version dm_ip_block =
  * *WIP*
  */
 
+struct drm_atomic_state *dm_atomic_state_alloc(struct drm_device *dev)
+{
+   struct dm_atomic_state *dm_state;
+
+   dm_state = kzalloc(sizeof(*dm_state), GFP_KERNEL);
+
+   if (!dm_state)
+   return NULL;
+
+   if (drm_atomic_state_init(dev, _state->base) < 0) {
+   kfree(dm_state);
+   return NULL;
+   }
+
+   return _state->base;
+}
+
+void dm_atomic_state_free(struct drm_atomic_state *state)
+{
+   struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
+
+   if (dm_state->context) {
+   dc_release_state(dm_state->context);
+   dm_state->context = NULL;
+   }
+
+   drm_atomic_state_default_release(state);
+   kfree(state);
+}
+
+void dm_atomic_state_clear(struct drm_atomic_state *state)
+{
+   struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
+
+   drm_atomic_state_default_clear(_state->base);
+}
+
 static const struct drm_mode_config_func

[PATCH 0/7] drm/amd/display: Drop DRM private objects from amdgpu_dm

2020-07-30 Thread Nicholas Kazlauskas
Based on the analysis of the bug from [1] the best course of action seems
to be swapping off of DRM private objects back to subclassing DRM atomic
state instead.

This patch series implements this change, but not yet the other changes
suggested in the threads from that bug - these will come later.

CCing dri-devel per Daniel's suggestion since this issue brought
some interesting misuse of private objects.

[1] https://bugzilla.kernel.org/show_bug.cgi?id=207383

Nicholas Kazlauskas (7):
  drm/amd/display: Store tiling_flags and tmz_surface on dm_plane_state
  drm/amd/display: Reset plane when tiling flags change
  drm/amd/display: Avoid using unvalidated tiling_flags and tmz_surface
in prepare_planes
  drm/amd/display: Use validated tiling_flags and tmz_surface in
commit_tail
  drm/amd/display: Reset plane for anything that's not a FAST update
  drm/amd/display: Drop dm_determine_update_type_for_commit
  drm/amd/display: Replace DRM private objects with subclassed DRM
atomic state

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 967 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  13 +-
 2 files changed, 343 insertions(+), 637 deletions(-)

-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 6/7] drm/amd/display: Drop dm_determine_update_type_for_commit

2020-07-30 Thread Nicholas Kazlauskas
[Why]
This was added in the past to solve the issue of not knowing when
to stall for medium and full updates in DM.

Since DC is ultimately decides what requires bandwidth changes we
wanted to make use of it directly to determine this.

The problem is that we can't actually pass any of the stream or surface
updates into DC global validation, so we don't actually check if the new
configuration is valid - we just validate the old existing config
instead and stall for outstanding commits to finish.

There's also the problem of grabbing the DRM private object for
pageflips which can lead to page faults in the case where commits
execute out of order and free a DRM private object state that was
still required for commit tail.

[How]
Now that we reset the plane in DM with the same conditions DC checks
we can have planes go through DC validation and we know when we need
to check and stall based on whether the stream or planes changed.

We mark lock_and_validation_needed whenever we've done this, so just
go back to using that instead of dm_determine_update_type_for_commit.

Since we'll skip resetting the plane for a pageflip we will no longer
grab the DRM private object for pageflips as well, avoiding the
page fault issued caused by pageflipping under load with commits
executing out of order.

Cc: Harry Wentland 
Cc: Bhawanpreet Lakha 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 199 ++
 1 file changed, 17 insertions(+), 182 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 2cbb29199e61..59829ec81694 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8542,161 +8542,6 @@ static int dm_update_plane_state(struct dc *dc,
return ret;
 }
 
-static int
-dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm,
-   struct drm_atomic_state *state,
-   enum surface_update_type *out_type)
-{
-   struct dc *dc = dm->dc;
-   struct dm_atomic_state *dm_state = NULL, *old_dm_state = NULL;
-   int i, j, num_plane, ret = 0;
-   struct drm_plane_state *old_plane_state, *new_plane_state;
-   struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state;
-   struct drm_crtc *new_plane_crtc;
-   struct drm_plane *plane;
-
-   struct drm_crtc *crtc;
-   struct drm_crtc_state *new_crtc_state, *old_crtc_state;
-   struct dm_crtc_state *new_dm_crtc_state, *old_dm_crtc_state;
-   struct dc_stream_status *status = NULL;
-   enum surface_update_type update_type = UPDATE_TYPE_FAST;
-   struct surface_info_bundle {
-   struct dc_surface_update surface_updates[MAX_SURFACES];
-   struct dc_plane_info plane_infos[MAX_SURFACES];
-   struct dc_scaling_info scaling_infos[MAX_SURFACES];
-   struct dc_flip_addrs flip_addrs[MAX_SURFACES];
-   struct dc_stream_update stream_update;
-   } *bundle;
-
-   bundle = kzalloc(sizeof(*bundle), GFP_KERNEL);
-
-   if (!bundle) {
-   DRM_ERROR("Failed to allocate update bundle\n");
-   /* Set type to FULL to avoid crashing in DC*/
-   update_type = UPDATE_TYPE_FULL;
-   goto cleanup;
-   }
-
-   for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
new_crtc_state, i) {
-
-   memset(bundle, 0, sizeof(struct surface_info_bundle));
-
-   new_dm_crtc_state = to_dm_crtc_state(new_crtc_state);
-   old_dm_crtc_state = to_dm_crtc_state(old_crtc_state);
-   num_plane = 0;
-
-   if (new_dm_crtc_state->stream != old_dm_crtc_state->stream) {
-   update_type = UPDATE_TYPE_FULL;
-   goto cleanup;
-   }
-
-   if (!new_dm_crtc_state->stream)
-   continue;
-
-   for_each_oldnew_plane_in_state(state, plane, old_plane_state, 
new_plane_state, j) {
-   struct dc_plane_info *plane_info = 
>plane_infos[num_plane];
-   struct dc_flip_addrs *flip_addr = 
>flip_addrs[num_plane];
-   struct dc_scaling_info *scaling_info = 
>scaling_infos[num_plane];
-
-   new_plane_crtc = new_plane_state->crtc;
-   new_dm_plane_state = to_dm_plane_state(new_plane_state);
-   old_dm_plane_state = to_dm_plane_state(old_plane_state);
-
-   if (plane->type == DRM_PLANE_TYPE_CURSOR)
-   continue;
-
-   if (new_dm_plane_state->dc_state != 
old_dm_plane_state->dc_state) {
-   update_type = UPDATE_TYPE_FULL;
-   goto cleanup;
-

[PATCH 1/2] drm/amd/display: Add missing DCN30 registers and fields for OTG_CRC_CNTL2

2020-07-13 Thread Nicholas Kazlauskas
[Why]
When enabling the debugfs for CRC capture we hit assertions caused by
register address and field masks and shifts missing.

[How]
We want these registers programmed, so add in the SRI/SF entries for
this register.

Cc: Bhawanpreet Lakha 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h 
b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
index d4106dd5a9b0..33f13c1e7520 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
@@ -98,6 +98,7 @@
SRI(OTG_GSL_WINDOW_Y, OTG, inst),\
SRI(OTG_VUPDATE_KEEPOUT, OTG, inst),\
SRI(OTG_DSC_START_POSITION, OTG, inst),\
+   SRI(OTG_CRC_CNTL2, OTG, inst),\
SRI(OTG_DRR_TRIGGER_WINDOW, OTG, inst),\
SRI(OTG_DRR_V_TOTAL_CHANGE, OTG, inst),\
SRI(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\
@@ -248,6 +249,10 @@
SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \
SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \
SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, 
mask_sh),\
+   SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\
+   SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\
+   SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\
+   SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\
SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\
SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\
SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\
@@ -280,6 +285,10 @@
SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \
SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \
SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, 
mask_sh),\
+   SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\
+   SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\
+   SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\
+   SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\
SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\
SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\
SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG2_SRC_SEL, mask_sh),\
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 2/2] drm/amd/display: Allow for vblank enabled with no active planes

2020-07-13 Thread Nicholas Kazlauskas
[Why]
CRC capture doesn't work when the active plane count is 0 since we
currently tie both vblank and pageflip interrupts to active_plane_count
greater than 0.

[How]
The frontend is what generates the vblank interrupts while the backend
is what generates pageflip interrupts. Both have a requirement for
the CRTC to be active, so control the overall interrupt state based
on that instead.

Pageflip interrupts need to be enabled based on active plane count, but
we actually rely on power gating to take care of disabling the interrupt
for us on pipes that can be power gated.

For pipes that can't be power gated it's still fine to leave it enabled
since the interrupt only triggers after the address has been written
to that particular pipe - which we won't be doing without an active
plane.

The issue we had before with this setup was that we couldn't force
the state back on. We were essentially manipulating the refcount
to enable or disable as needed in a two pass approach.

However, there is a function that solves this problem more elegantly:
amdgpu_irq_update() will unconditionally call the set based on what it
thinks the current enablement state is.

This leaves two future TODO items for our IRQ handling:
- Disabling IRQs in commit tail instead of atomic commit
- Mapping the pageflip interrupt to VUPDATE or something that's tied to
  the frontend instead of the backend since the mapping to CRTC is not
  correct

Cc: Bhawanpreet Lakha 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 168 --
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   1 -
 2 files changed, 78 insertions(+), 91 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index d9f8e9c26390..05160c6bbc03 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4719,7 +4719,6 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc)
}
 
state->active_planes = cur->active_planes;
-   state->interrupts_enabled = cur->interrupts_enabled;
state->vrr_params = cur->vrr_params;
state->vrr_infopacket = cur->vrr_infopacket;
state->abm_level = cur->abm_level;
@@ -5393,29 +5392,19 @@ static int count_crtc_active_planes(struct 
drm_crtc_state *new_crtc_state)
return num_active;
 }
 
-/*
- * Sets whether interrupts should be enabled on a specific CRTC.
- * We require that the stream be enabled and that there exist active
- * DC planes on the stream.
- */
-static void
-dm_update_crtc_interrupt_state(struct drm_crtc *crtc,
-  struct drm_crtc_state *new_crtc_state)
+static void dm_update_crtc_active_planes(struct drm_crtc *crtc,
+struct drm_crtc_state *new_crtc_state)
 {
struct dm_crtc_state *dm_new_crtc_state =
to_dm_crtc_state(new_crtc_state);
 
dm_new_crtc_state->active_planes = 0;
-   dm_new_crtc_state->interrupts_enabled = false;
 
if (!dm_new_crtc_state->stream)
return;
 
dm_new_crtc_state->active_planes =
count_crtc_active_planes(new_crtc_state);
-
-   dm_new_crtc_state->interrupts_enabled =
-   dm_new_crtc_state->active_planes > 0;
 }
 
 static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
@@ -5426,13 +5415,7 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc 
*crtc,
struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state);
int ret = -EINVAL;
 
-   /*
-* Update interrupt state for the CRTC. This needs to happen whenever
-* the CRTC has changed or whenever any of its planes have changed.
-* Atomic check satisfies both of these requirements since the CRTC
-* is added to the state by DRM during drm_atomic_helper_check_planes.
-*/
-   dm_update_crtc_interrupt_state(crtc, state);
+   dm_update_crtc_active_planes(crtc, state);
 
if (unlikely(!dm_crtc_state->stream &&
 modeset_required(state, NULL, dm_crtc_state->stream))) {
@@ -6547,8 +6530,10 @@ static void manage_dm_interrupts(struct amdgpu_device 
*adev,
 bool enable)
 {
/*
-* this is not correct translation but will work as soon as VBLANK
-* constant is the same as PFLIP
+* We have no guarantee that the frontend index maps to the same
+* backend index - some even map to more than one.
+*
+* TODO: Use a different interrupt or check DC itself for the mapping.
 */
int irq_type =
amdgpu_display_crtc_idx_to_irq_type(
@@ -6571,6 +6556,19 @@ static void manage_dm_interrupts(struct amdgpu_device 
*adev,
}
 }
 
+static void dm_update_pflip_irq_state(struct amdgpu_device *adev,
+  

[PATCH] drm/amd/display: Fix CSC remap matrix not being applied on dcn30

2020-07-08 Thread Nicholas Kazlauskas
[Why]
DCN3 has two gamut remap matrices. When using CSC adjustment the CM
remap is set to bypass and MPCC remap is used. However to bypass CM
some state in the context is modified and not restored correctly
resulting in subsequent calls to disable MPCC remap as well.

[How]
Fix logic for save/restore of remap enable flag when programming MPCC
remap matrix.

Cc: Bhawanpreet Lakha 
Signed-off-by: Aric Cyr 
Signed-off-by: Nicholas Kazlauskas 
---
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c| 27 ++-
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index 5621c95177d2..7725a406c16e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -1482,22 +1482,23 @@ static void dcn20_update_dchubp_dpp(
 
memset(, 0, sizeof(adjust));
adjust.gamut_adjust_type = 
GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
-   /* save the enablement of gamut remap for dpp*/
+
+   /* save the enablement of gamut remap for dpp */
enable_remap_dpp = 
pipe_ctx->stream->gamut_remap_matrix.enable_remap;
-   /*force bypass gamut remap for dpp/cm*/
+
+   /* force bypass gamut remap for dpp/cm */
pipe_ctx->stream->gamut_remap_matrix.enable_remap = 
false;
dc->hwss.program_gamut_remap(pipe_ctx);
-   /*restore gamut remap flag for the top plane and use 
this remap into mpc*/
-   if (pipe_ctx->top_pipe == NULL)
-   
pipe_ctx->stream->gamut_remap_matrix.enable_remap = enable_remap_dpp;
-   else
-   
pipe_ctx->stream->gamut_remap_matrix.enable_remap = false;
-
-   if (pipe_ctx->stream->gamut_remap_matrix.enable_remap 
== true) {
-   adjust.gamut_adjust_type = 
GRAPHICS_GAMUT_ADJUST_TYPE_SW;
-   for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; 
i++)
-   adjust.temperature_matrix[i] =
-   
pipe_ctx->stream->gamut_remap_matrix.matrix[i];
+
+   /* restore gamut remap flag and use this remap into mpc 
*/
+   pipe_ctx->stream->gamut_remap_matrix.enable_remap = 
enable_remap_dpp;
+
+   /* build remap matrix for top plane if enabled */
+   if (enable_remap_dpp && pipe_ctx->top_pipe == NULL) {
+   adjust.gamut_adjust_type = 
GRAPHICS_GAMUT_ADJUST_TYPE_SW;
+   for (i = 0; i < 
CSC_TEMPERATURE_MATRIX_SIZE; i++)
+   adjust.temperature_matrix[i] =
+   
pipe_ctx->stream->gamut_remap_matrix.matrix[i];
}
mpc->funcs->set_gamut_remap(mpc, mpcc_id, );
} else
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH] drm/amd/display: Use VUPDATE_NO_LOCK instead of VUPDATE for dcn30

2020-07-08 Thread Nicholas Kazlauskas
[Why]
Soft hangs occur when FreeSync is engaged since we utilize VUPDATE
(which doesn't fire when holding the pipe lock) to send back vblank
events when FreeSync is active.

[How]
The alternative (working) interrupt source for this mechanism is
VUPDATE_NO_LOCK. We already use this all other DCN revisions so align
dcn30 with those as well.

Cc: Bhawanpreet Lakha 
Signed-off-by: Nicholas Kazlauskas 
---
 .../display/dc/irq/dcn30/irq_service_dcn30.c  | 28 ---
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c 
b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c
index dd4d7a1dc3b6..49689f71f4f1 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c
@@ -169,6 +169,11 @@ static const struct irq_source_info_funcs 
pflip_irq_info_funcs = {
.ack = NULL
 };
 
+static const struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = {
+   .set = NULL,
+   .ack = NULL
+};
+
 static const struct irq_source_info_funcs vblank_irq_info_funcs = {
.set = NULL,
.ack = NULL
@@ -228,12 +233,15 @@ static const struct irq_source_info_funcs 
vblank_irq_info_funcs = {
.funcs = _irq_info_funcs\
}
 
-#define vupdate_int_entry(reg_num)\
+/* vupdate_no_lock_int_entry maps to DC_IRQ_SOURCE_VUPDATEx, to match semantic
+ * of DCE's DC_IRQ_SOURCE_VUPDATEx.
+ */
+#define vupdate_no_lock_int_entry(reg_num)\
[DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\
IRQ_REG_ENTRY(OTG, reg_num,\
-   OTG_GLOBAL_SYNC_STATUS, VUPDATE_INT_EN,\
-   OTG_GLOBAL_SYNC_STATUS, VUPDATE_EVENT_CLEAR),\
-   .funcs = _irq_info_funcs\
+   OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_INT_EN,\
+   OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR),\
+   .funcs = _no_lock_irq_info_funcs\
}
 
 #define vblank_int_entry(reg_num)\
@@ -340,12 +348,12 @@ irq_source_info_dcn30[DAL_IRQ_SOURCES_NUMBER] = {
dc_underflow_int_entry(6),
[DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(),
[DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(),
-   vupdate_int_entry(0),
-   vupdate_int_entry(1),
-   vupdate_int_entry(2),
-   vupdate_int_entry(3),
-   vupdate_int_entry(4),
-   vupdate_int_entry(5),
+   vupdate_no_lock_int_entry(0),
+   vupdate_no_lock_int_entry(1),
+   vupdate_no_lock_int_entry(2),
+   vupdate_no_lock_int_entry(3),
+   vupdate_no_lock_int_entry(4),
+   vupdate_no_lock_int_entry(5),
vblank_int_entry(0),
vblank_int_entry(1),
vblank_int_entry(2),
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH] drm/amd/display: Add missing CW4 programming for DCN30

2020-07-07 Thread Nicholas Kazlauskas
[Why]
To support inbox1 in CW4 we need to actually program CW4 instead of
region 4 for newer firmware.

This is done correctly on DCN20/DCN21 but this code wasn't added to
DCN30.

[How]
Copy over the missing code. It doesn't need address translation since
DCN30 uses virtual addressing.

Cc: Bhawanpreet Lakha 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/dmub/src/dmub_dcn30.c | 21 ++-
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c 
b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
index ba8d0bfb5522..215178b8d415 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
@@ -153,11 +153,22 @@ void dmub_dcn30_setup_windows(struct dmub_srv *dmub,
 
offset = cw4->offset;
 
-   REG_WRITE(DMCUB_REGION4_OFFSET, offset.u.low_part);
-   REG_WRITE(DMCUB_REGION4_OFFSET_HIGH, offset.u.high_part);
-   REG_SET_2(DMCUB_REGION4_TOP_ADDRESS, 0, DMCUB_REGION4_TOP_ADDRESS,
- cw4->region.top - cw4->region.base - 1, DMCUB_REGION4_ENABLE,
- 1);
+   /* New firmware can support CW4. */
+   if (dmub->fw_version > DMUB_FW_VERSION(1, 0, 10)) {
+   REG_WRITE(DMCUB_REGION3_CW4_OFFSET, offset.u.low_part);
+   REG_WRITE(DMCUB_REGION3_CW4_OFFSET_HIGH, offset.u.high_part);
+   REG_WRITE(DMCUB_REGION3_CW4_BASE_ADDRESS, cw4->region.base);
+   REG_SET_2(DMCUB_REGION3_CW4_TOP_ADDRESS, 0,
+ DMCUB_REGION3_CW4_TOP_ADDRESS, cw4->region.top,
+ DMCUB_REGION3_CW4_ENABLE, 1);
+   } else {
+   REG_WRITE(DMCUB_REGION4_OFFSET, offset.u.low_part);
+   REG_WRITE(DMCUB_REGION4_OFFSET_HIGH, offset.u.high_part);
+   REG_SET_2(DMCUB_REGION4_TOP_ADDRESS, 0,
+ DMCUB_REGION4_TOP_ADDRESS,
+ cw4->region.top - cw4->region.base - 1,
+ DMCUB_REGION4_ENABLE, 1);
+   }
 
offset = cw5->offset;
 
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH] drm/amd/display: Only revalidate bandwidth on medium and fast updates

2020-06-29 Thread Nicholas Kazlauskas
[Why]
Changes that are fast don't require updating DLG parameters making
this call unnecessary. Considering this is an expensive call it should
not be done on every flip.

DML touches clocks, p-state support, DLG params and a few other DC
internal flags and these aren't expected during fast. A hang has been
reported with this change when called on every flip which suggests that
modifying these fields is not recommended behavior on fast updates.

[How]
Guard the validation to only happen if update type isn't FAST.

Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1191
Fixes: e1995f0909e3 ("drm/amd/display: Revalidate bandwidth before commiting DC 
updates")
Cc: Hersen Wu 
Cc: Bhawanpreet Lakha 
Cc: Rodrigo Siqueira 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/core/dc.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 67402d75e67e..942ceb0f6383 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -2607,10 +2607,12 @@ void dc_commit_updates_for_stream(struct dc *dc,
 
copy_stream_update_to_stream(dc, context, stream, stream_update);
 
-   if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
-   DC_ERROR("Mode validation failed for stream update!\n");
-   dc_release_state(context);
-   return;
+   if (update_type > UPDATE_TYPE_FAST) {
+   if (!dc->res_pool->funcs->validate_bandwidth(dc, context, 
false)) {
+   DC_ERROR("Mode validation failed for stream update!\n");
+   dc_release_state(context);
+   return;
+   }
}
 
commit_planes_for_stream(
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH] drm/amd/display: Only actually breakpoint if DEBUG_KERNEL_DC is enabled

2020-06-03 Thread Nicholas Kazlauskas
To match previous behavior and to not hang the kernel if someone
accidentally builds with KGDB enabled.

Fixes: 4324a1752045 ("drm/amd/display: Make BREAK_TO_DEBUGGER() a debug print")

Cc: Harry Wentland 
Cc: Alex Deucher 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/os_types.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h 
b/drivers/gpu/drm/amd/display/dc/os_types.h
index 604ceb6c0375..c3bbfe397e8d 100644
--- a/drivers/gpu/drm/amd/display/dc/os_types.h
+++ b/drivers/gpu/drm/amd/display/dc/os_types.h
@@ -111,7 +111,7 @@
 #define ASSERT(expr) WARN_ON_ONCE(!(expr))
 #endif
 
-#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB)
+#if defined(CONFIG_DEBUG_KERNEL_DC) && (defined(CONFIG_HAVE_KGDB) || 
defined(CONFIG_KGDB))
 #define BREAK_TO_DEBUGGER() \
do { \
DRM_DEBUG_DRIVER("%s():%d\n", __func__, __LINE__); \
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH] drm/amd/display: Revalidate bandwidth before commiting DC updates

2020-06-02 Thread Nicholas Kazlauskas
[Why]
Whenever we switch between tiled formats without also switching pixel
formats or doing anything else that recreates the DC plane state we
can run into underflow or hangs since we're not updating the
DML parameters before committing to the hardware.

[How]
If the update type is FULL then call validate_bandwidth again to update
the DML parmeters before committing the state.

This is basically just a workaround and protective measure against
update types being added DC where we could run into this issue in
the future.

We can only fully validate the state in advance before applying it to
the hardware if we recreate all the plane and stream states since
we can't modify what's currently in use.

The next step is to update DM to ensure that we're creating the plane
and stream states for whatever could potentially be a full update in
DC to pre-emptively recreate the state for DC global validation.

The workaround can stay until this has been fixed in DM.

Cc: Hersen Wu 
Cc: Harry Wentland 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/core/dc.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 04c3d9f7e323..00a4f679759f 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -2523,6 +2523,12 @@ void dc_commit_updates_for_stream(struct dc *dc,
 
copy_stream_update_to_stream(dc, context, stream, stream_update);
 
+   if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
+   DC_ERROR("Mode validation failed for stream update!\n");
+   dc_release_state(context);
+   return;
+   }
+
commit_planes_for_stream(
dc,
srf_updates,
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH] drm/amd/display: Make BREAK_TO_DEBUGGER() a debug print

2020-05-22 Thread Nicholas Kazlauskas
[Why]
Warnings in the kernel are generally treated as errors.

The BREAK_TO_DEBUGGER macro is not a critical error or warning, but
rather intended for developer use to help investigate behavior and
sequences for other issues.

We do still make use of DC_ERROR/ASSERT(0) in various places in the
code for things that are genuine issues.

Since most developers don't actually KGDB while debugging the kernel
these essentially would have no value on their own since the KGDB
breakpoint wouldn't trigger - ASSERT(0) was used as a shortcut to get
a stacktrace.

[How]
Turn it into a DRM_DEBUG_DRIVER print instead. We unfortunately lose
the stacktrace, but we still do retain some of the useful debug
information this offers by having at least the function and line
number loggable.

If KGDB is supported in the kernel this will still trigger a real
breakpoint as well.

Cc: Harry Wentland 
Cc: Leo Li 
Cc: Bhawanpreet Lakha 
Cc: Rodrigo Siqueira 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/os_types.h | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h 
b/drivers/gpu/drm/amd/display/dc/os_types.h
index 6d7bca562eec..604ceb6c0375 100644
--- a/drivers/gpu/drm/amd/display/dc/os_types.h
+++ b/drivers/gpu/drm/amd/display/dc/os_types.h
@@ -111,7 +111,15 @@
 #define ASSERT(expr) WARN_ON_ONCE(!(expr))
 #endif
 
-#define BREAK_TO_DEBUGGER() ASSERT(0)
+#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB)
+#define BREAK_TO_DEBUGGER() \
+   do { \
+   DRM_DEBUG_DRIVER("%s():%d\n", __func__, __LINE__); \
+   kgdb_breakpoint(); \
+   } while (0)
+#else
+#define BREAK_TO_DEBUGGER() DRM_DEBUG_DRIVER("%s():%d\n", __func__, __LINE__)
+#endif
 
 #define DC_ERR(...)  do { \
dm_error(__VA_ARGS__); \
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH] drm/amd/display: Fix vblank and pageflip event handling for FreeSync

2020-05-06 Thread Nicholas Kazlauskas
[Why]
We're the drm vblank event a frame too early in the case where the
pageflip happens close to VUPDATE and ends up blocking the signal.

The implementation in DM was previously correct *before* we started
sending vblank events from VSTARTUP unconditionally to handle cases
where HUBP was off, OTG was ON and userspace was still requesting some
DRM planes enabled. As part of that patch series we dropped VUPDATE
since it was deemed close enough to VSTARTUP, but there's a key
difference betweeen VSTARTUP and VUPDATE - the VUPDATE signal can be
blocked if we're holding the pipe lock.

There was a fix recently to revert the unconditional behavior for the
DCN VSTARTUP vblank event since it was sending the pageflip event on
the wrong frame - once again, due to blocking VUPDATE and having the
address start scanning out two frames later.

The problem with this fix is it didn't update the logic that calls
drm_crtc_handle_vblank(), so the timestamps are totally bogus now.

[How]
Essentially reverts most of the original VSTARTUP series but retains
the behavior to send back events when active planes == 0.

Some refactoring/cleanup was done to not have duplicated code in both
the handlers.

Fixes: 16f17eda8bad ("drm/amd/display: Send vblank and user events at vsartup 
for DCN")
Fixes: 3a2ce8d66a4b ("drm/amd/display: Disable VUpdate interrupt for DCN 
hardware")
Fixes: 2b5aed9ac3f7 ("drm/amd/display: Fix pageflip event race condition for 
DCN.")

Cc: Leo Li 
Cc: Mario Kleiner 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 137 +++---
 1 file changed, 55 insertions(+), 82 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 59f1d4a94f12..30ce28f7c444 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -441,7 +441,7 @@ static void dm_vupdate_high_irq(void *interrupt_params)
 
 /**
  * dm_crtc_high_irq() - Handles CRTC interrupt
- * @interrupt_params: ignored
+ * @interrupt_params: used for determining the CRTC instance
  *
  * Handles the CRTC/VSYNC interrupt by notfying DRM's VBLANK
  * event handler.
@@ -455,70 +455,6 @@ static void dm_crtc_high_irq(void *interrupt_params)
unsigned long flags;
 
acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - 
IRQ_TYPE_VBLANK);
-
-   if (acrtc) {
-   acrtc_state = to_dm_crtc_state(acrtc->base.state);
-
-   DRM_DEBUG_VBL("crtc:%d, vupdate-vrr:%d\n",
- acrtc->crtc_id,
- amdgpu_dm_vrr_active(acrtc_state));
-
-   /* Core vblank handling at start of front-porch is only possible
-* in non-vrr mode, as only there vblank timestamping will give
-* valid results while done in front-porch. Otherwise defer it
-* to dm_vupdate_high_irq after end of front-porch.
-*/
-   if (!amdgpu_dm_vrr_active(acrtc_state))
-   drm_crtc_handle_vblank(>base);
-
-   /* Following stuff must happen at start of vblank, for crc
-* computation and below-the-range btr support in vrr mode.
-*/
-   amdgpu_dm_crtc_handle_crc_irq(>base);
-
-   if (acrtc_state->stream && adev->family >= AMDGPU_FAMILY_AI &&
-   acrtc_state->vrr_params.supported &&
-   acrtc_state->freesync_config.state == 
VRR_STATE_ACTIVE_VARIABLE) {
-   spin_lock_irqsave(>ddev->event_lock, flags);
-   mod_freesync_handle_v_update(
-   adev->dm.freesync_module,
-   acrtc_state->stream,
-   _state->vrr_params);
-
-   dc_stream_adjust_vmin_vmax(
-   adev->dm.dc,
-   acrtc_state->stream,
-   _state->vrr_params.adjust);
-   spin_unlock_irqrestore(>ddev->event_lock, flags);
-   }
-   }
-}
-
-#if defined(CONFIG_DRM_AMD_DC_DCN)
-/**
- * dm_dcn_crtc_high_irq() - Handles VStartup interrupt for DCN generation ASICs
- * @interrupt params - interrupt parameters
- *
- * Notify DRM's vblank event handler at VSTARTUP
- *
- * Unlike DCE hardware, we trigger the handler at VSTARTUP. at which:
- * * We are close enough to VUPDATE - the point of no return for hw
- * * We are in the fixed portion of variable front porch when vrr is enabled
- * * We are before VUPDATE, where double-buffered vrr registers are swapped
- *
- * It is therefore the correct place to signal vblank, send user flip events,
- * and update VRR.
- */
-static void dm_dcn_crtc_high_irq(void *interrupt_param

[PATCH] drm/amd/display: Only enable cursor on pipes that need it

2020-01-30 Thread Nicholas Kazlauskas
[Why]
In current code we're essentially drawing the cursor on every pipe
that contains it. This only works when the planes have the same
scaling for src to dest rect, otherwise we'll get "double cursor" where
one cursor is incorrectly filtered and offset from the real position.

[How]
Without dedicated cursor planes on DCN we require at least one pipe
that matches the scaling of the current timing.

This is an optimization and workaround for the most common case where
the top-most plane is not scaled but the bottom-most plane is scaled.

Whenever a pipe has a parent pipe in the blending tree whose recout
fully contains the current pipe we can disable the pipe.

This only applies when the pipe is actually visible of course.

Signed-off-by: Nicholas Kazlauskas 
---
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 30 +++
 1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index f2127afb37b2..1008ac8a0f2a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -2911,6 +2911,33 @@ void dcn10_update_dchub(struct dce_hwseq *hws, struct 
dchub_init_data *dh_data)
hubbub->funcs->update_dchub(hubbub, dh_data);
 }
 
+static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
+{
+   struct pipe_ctx *test_pipe;
+   const struct rect *r1 = _ctx->plane_res.scl_data.recout, *r2;
+   int r1_r = r1->x + r1->width, r1_b = r1->y + r1->height, r2_r, r2_b;
+
+   /**
+* Disable the cursor if there's another pipe above this with a
+* plane that contains this pipe's viewport to prevent double cursor
+* and incorrect scaling artifacts.
+*/
+   for (test_pipe = pipe_ctx->top_pipe; test_pipe;
+test_pipe = test_pipe->top_pipe) {
+   if (!test_pipe->plane_state->visible)
+   continue;
+
+   r2 = _pipe->plane_res.scl_data.recout;
+   r2_r = r2->x + r2->width;
+   r2_b = r2->y + r2->height;
+
+   if (r1->x >= r2->x && r1->y >= r2->y && r1_r <= r2_r && r1_b <= 
r2_b)
+   return true;
+   }
+
+   return false;
+}
+
 void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
 {
struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
@@ -2956,6 +2983,9 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
== PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
pos_cpy.enable = false;
 
+   if (pos_cpy.enable && dcn10_can_pipe_disable_cursor(pipe_ctx))
+   pos_cpy.enable = false;
+
// Swap axis and mirror horizontally
if (param.rotation == ROTATION_ANGLE_90) {
uint32_t temp_x = pos_cpy.x;
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 01/11] drm/amdgpu: Add ucode support for DMCUB

2019-10-28 Thread Nicholas Kazlauskas
The DMCUB is a secondary DMCU (Display MicroController Unit) that has
its own separate firmware. It's required for DMCU support on Renoir.

Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 11 ++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h |  9 +
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index 833fc4b68940..9ef312428231 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -447,6 +447,7 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device 
*adev,
const struct common_firmware_header *header = NULL;
const struct gfx_firmware_header_v1_0 *cp_hdr = NULL;
const struct dmcu_firmware_header_v1_0 *dmcu_hdr = NULL;
+   const struct dmcub_firmware_header_v1_0 *dmcub_hdr = NULL;
 
if (NULL == ucode->fw)
return 0;
@@ -460,6 +461,7 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device 
*adev,
header = (const struct common_firmware_header *)ucode->fw->data;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
dmcu_hdr = (const struct dmcu_firmware_header_v1_0 *)ucode->fw->data;
+   dmcub_hdr = (const struct dmcub_firmware_header_v1_0 *)ucode->fw->data;
 
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP ||
(ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC1 &&
@@ -470,7 +472,8 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device 
*adev,
 ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM &&
 ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM &&
 ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_ERAM &&
-ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_INTV)) {
+ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_INTV &&
+ucode->ucode_id != AMDGPU_UCODE_ID_DMCUB)) {
ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes);
 
memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
@@ -506,6 +509,12 @@ static int amdgpu_ucode_init_single_fw(struct 
amdgpu_device *adev,
  
le32_to_cpu(header->ucode_array_offset_bytes) +
  
le32_to_cpu(dmcu_hdr->intv_offset_bytes)),
   ucode->ucode_size);
+   } else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCUB) {
+   ucode->ucode_size = le32_to_cpu(dmcub_hdr->inst_const_bytes);
+   memcpy(ucode->kaddr,
+  (void *)((uint8_t *)ucode->fw->data +
+   le32_to_cpu(header->ucode_array_offset_bytes)),
+  ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL) {
ucode->ucode_size = 
adev->gfx.rlc.save_restore_list_cntl_size_bytes;
memcpy(ucode->kaddr, adev->gfx.rlc.save_restore_list_cntl,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index 410587b950f3..eaf2d5b9c92f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -251,6 +251,13 @@ struct dmcu_firmware_header_v1_0 {
uint32_t intv_size_bytes;  /* size of interrupt vectors, in bytes */
 };
 
+/* version_major=1, version_minor=0 */
+struct dmcub_firmware_header_v1_0 {
+   struct common_firmware_header header;
+   uint32_t inst_const_bytes; /* size of instruction region, in bytes */
+   uint32_t bss_data_bytes; /* size of bss/data region, in bytes */
+};
+
 /* header is fixed size */
 union amdgpu_firmware_header {
struct common_firmware_header common;
@@ -268,6 +275,7 @@ union amdgpu_firmware_header {
struct sdma_firmware_header_v1_1 sdma_v1_1;
struct gpu_info_firmware_header_v1_0 gpu_info;
struct dmcu_firmware_header_v1_0 dmcu;
+   struct dmcub_firmware_header_v1_0 dmcub;
uint8_t raw[0x100];
 };
 
@@ -307,6 +315,7 @@ enum AMDGPU_UCODE_ID {
AMDGPU_UCODE_ID_DMCU_INTV,
AMDGPU_UCODE_ID_VCN0_RAM,
AMDGPU_UCODE_ID_VCN1_RAM,
+   AMDGPU_UCODE_ID_DMCUB,
AMDGPU_UCODE_ID_MAXIMUM,
 };
 
-- 
2.20.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 05/11] drm/amd/display: Change dmcu init sequence for dmcub loading dmcu FW.

2019-10-28 Thread Nicholas Kazlauskas
From: Yongqiang Sun 

[Why]
DMCU isn't intiliazed properly by dmcub loading due to dmcub initialize
sequence.

[How]
Change dmcu init sequece to meet dmcub initilize.

Signed-off-by: Yongqiang Sun 
Reviewed-by: Tony Cheng 
---
 drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 79 +++
 drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 13 +++
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c |  2 +-
 .../drm/amd/display/dc/dcn21/dcn21_resource.c |  4 +-
 drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h  |  2 +
 5 files changed, 97 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c 
b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
index ba995d3f2318..3417100d51e4 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
@@ -59,6 +59,12 @@
 #define MCP_BL_SET_PWM_FRAC 0x6A  /* Enable or disable Fractional PWM */
 #define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK   0x0001L
 
+// PSP FW version
+#define mmMP0_SMN_C2PMSG_580x1607A
+
+//Register access policy version
+#define mmMP0_SMN_C2PMSG_910x1609B
+
 static bool dce_dmcu_init(struct dmcu *dmcu)
 {
// Do nothing
@@ -373,6 +379,7 @@ static bool dcn10_dmcu_init(struct dmcu *dmcu)
const struct dc_config *config = >ctx->dc->config;
bool status = false;
 
+   PERF_TRACE();
/*  Definition of DC_DMCU_SCRATCH
 *  0 : firmare not loaded
 *  1 : PSP load DMCU FW but not initialized
@@ -429,9 +436,23 @@ static bool dcn10_dmcu_init(struct dmcu *dmcu)
break;
}
 
+   PERF_TRACE();
return status;
 }
 
+#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
+static bool dcn21_dmcu_init(struct dmcu *dmcu)
+{
+   struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
+   uint32_t dmcub_psp_version = REG_READ(DMCUB_SCRATCH15);
+
+   if (dmcu->auto_load_dmcu && dmcub_psp_version == 0) {
+   return false;
+   }
+
+   return dcn10_dmcu_init(dmcu);
+}
+#endif
 
 static bool dcn10_dmcu_load_iram(struct dmcu *dmcu,
unsigned int start_offset,
@@ -818,6 +839,21 @@ static const struct dmcu_funcs dcn20_funcs = {
 };
 #endif
 
+#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
+static const struct dmcu_funcs dcn21_funcs = {
+   .dmcu_init = dcn21_dmcu_init,
+   .load_iram = dcn10_dmcu_load_iram,
+   .set_psr_enable = dcn10_dmcu_set_psr_enable,
+   .setup_psr = dcn10_dmcu_setup_psr,
+   .get_psr_state = dcn10_get_dmcu_psr_state,
+   .set_psr_wait_loop = dcn10_psr_wait_loop,
+   .get_psr_wait_loop = dcn10_get_psr_wait_loop,
+   .is_dmcu_initialized = dcn10_is_dmcu_initialized,
+   .lock_phy = dcn20_lock_phy,
+   .unlock_phy = dcn20_unlock_phy
+};
+#endif
+
 static void dce_dmcu_construct(
struct dce_dmcu *dmcu_dce,
struct dc_context *ctx,
@@ -836,6 +872,26 @@ static void dce_dmcu_construct(
dmcu_dce->dmcu_mask = dmcu_mask;
 }
 
+#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
+static void dcn21_dmcu_construct(
+   struct dce_dmcu *dmcu_dce,
+   struct dc_context *ctx,
+   const struct dce_dmcu_registers *regs,
+   const struct dce_dmcu_shift *dmcu_shift,
+   const struct dce_dmcu_mask *dmcu_mask)
+{
+   uint32_t psp_version = 0;
+
+   dce_dmcu_construct(dmcu_dce, ctx, regs, dmcu_shift, dmcu_mask);
+
+   if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
+   psp_version = dm_read_reg(ctx, mmMP0_SMN_C2PMSG_58);
+   dmcu_dce->base.auto_load_dmcu = (psp_version > 0x00110029);
+   dmcu_dce->base.psp_version = psp_version;
+   }
+}
+#endif
+
 struct dmcu *dce_dmcu_create(
struct dc_context *ctx,
const struct dce_dmcu_registers *regs,
@@ -903,6 +959,29 @@ struct dmcu *dcn20_dmcu_create(
 }
 #endif
 
+#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
+struct dmcu *dcn21_dmcu_create(
+   struct dc_context *ctx,
+   const struct dce_dmcu_registers *regs,
+   const struct dce_dmcu_shift *dmcu_shift,
+   const struct dce_dmcu_mask *dmcu_mask)
+{
+   struct dce_dmcu *dmcu_dce = kzalloc(sizeof(*dmcu_dce), GFP_KERNEL);
+
+   if (dmcu_dce == NULL) {
+   BREAK_TO_DEBUGGER();
+   return NULL;
+   }
+
+   dcn21_dmcu_construct(
+   dmcu_dce, ctx, regs, dmcu_shift, dmcu_mask);
+
+   dmcu_dce->base.funcs = _funcs;
+
+   return _dce->base;
+}
+#endif
+
 void dce_dmcu_destroy(struct dmcu **dmcu)
 {
struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(*dmcu);
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h 
b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h
index cc8587683b4b..1a42b2cbb21b 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h
@@ -71,6 +71,10 @@
DMCU_COMMON_REG_LIST_DCE_BASE(), \
SR(DMU_MEM_PWR_CNTL)
 
+#define 

[PATCH 08/11] drm/amdgpu: Add DMCUB to firmware query interface

2019-10-28 Thread Nicholas Kazlauskas
The DMCUB firmware version can be read using the AMDGPU_INFO ioctl
or the amdgpu_firmware_info debugfs entry.

Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 12 
 include/uapi/drm/amdgpu_drm.h   |  3 +++
 2 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index e3632825bbc2..1ff0202a900d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -294,6 +294,10 @@ static int amdgpu_firmware_info(struct 
drm_amdgpu_info_firmware *fw_info,
fw_info->ver = adev->dm.dmcu_fw_version;
fw_info->feature = 0;
break;
+   case AMDGPU_INFO_FW_DMCUB:
+   fw_info->ver = adev->dm.dmcub_fw_version;
+   fw_info->feature = 0;
+   break;
default:
return -EINVAL;
}
@@ -1392,6 +1396,14 @@ static int amdgpu_debugfs_firmware_info(struct seq_file 
*m, void *data)
seq_printf(m, "DMCU feature version: %u, firmware version: 0x%08x\n",
   fw_info.feature, fw_info.ver);
 
+   /* DMCUB */
+   query_fw.fw_type = AMDGPU_INFO_FW_DMCUB;
+   ret = amdgpu_firmware_info(_info, _fw, adev);
+   if (ret)
+   return ret;
+   seq_printf(m, "DMCUB feature version: %u, firmware version: 0x%08x\n",
+  fw_info.feature, fw_info.ver);
+
 
seq_printf(m, "VBIOS version: %s\n", ctx->vbios_version);
 
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index 391c9c1bdba4..f75c6957064d 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -714,6 +714,9 @@ struct drm_amdgpu_cs_chunk_data {
/* Subquery id: Query DMCU firmware version */
#define AMDGPU_INFO_FW_DMCU 0x12
#define AMDGPU_INFO_FW_TA   0x13
+   /* Subquery id: Query DMCUB firmware version */
+   #define AMDGPU_INFO_FW_DMCUB0x14
+
 /* number of bytes moved for TTM migration */
 #define AMDGPU_INFO_NUM_BYTES_MOVED0x0f
 /* the used VRAM size */
-- 
2.20.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 10/11] drm/amd/display: Register DMUB service with DC

2019-10-28 Thread Nicholas Kazlauskas
[Why]
DC can utilize the DMUB server to send commands to the DMUB but it's
the DM responsibility to pass it the service to use.

[How]
Create the dc_dmub_srv after we finish initializing the dmub_srv.
Cleanup the dc_dmub_srv before destroying the dmub_srv or dc.

Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 230fd0155463..920e84e40bbb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -34,6 +34,7 @@
 #include "dmub/inc/dmub_srv.h"
 #include "dc/inc/hw/dmcu.h"
 #include "dc/inc/hw/abm.h"
+#include "dc/dc_dmub_srv.h"
 #endif
 
 #include "vid.h"
@@ -803,6 +804,12 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu);
}
 
+   adev->dm.dc->ctx->dmub_srv = dc_dmub_srv_create(adev->dm.dc, dmub_srv);
+   if (!adev->dm.dc->ctx->dmub_srv) {
+   DRM_ERROR("Couldn't allocate DC DMUB server!\n");
+   return -ENOMEM;
+   }
+
DRM_INFO("DMUB hardware initialized: version=0x%08X\n",
 adev->dm.dmcub_fw_version);
 
@@ -976,6 +983,11 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
dc_deinit_callbacks(adev->dm.dc);
 #endif
 #ifdef CONFIG_DRM_AMD_DC_DMUB
+   if (adev->dm.dc->ctx->dmub_srv) {
+   dc_dmub_srv_destroy(>dm.dc->ctx->dmub_srv);
+   adev->dm.dc->ctx->dmub_srv = NULL;
+   }
+
if (adev->dm.dmub_bo)
amdgpu_bo_free_kernel(>dm.dmub_bo,
  >dm.dmub_bo_gpu_addr,
-- 
2.20.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 09/11] drm/amd/display: Add DMUB support to DC

2019-10-28 Thread Nicholas Kazlauskas
DC will use DMUB for command submission and flow control during
initialization.

Register offloading as well as submitting some BIOS commands are part
of the DC internal interface but are guarded behind debug options.

It won't be functional in amdgpu_dm yet since we don't pass the
DMUB service to DC for use.

Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/Makefile   |   6 +-
 .../drm/amd/display/dc/bios/command_table2.c  |  91 ++
 drivers/gpu/drm/amd/display/dc/core/dc.c  |   8 +
 drivers/gpu/drm/amd/display/dc/dc.h   |  12 +
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c  | 119 
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h  |  60 
 drivers/gpu/drm/amd/display/dc/dc_helper.c| 273 ++
 drivers/gpu/drm/amd/display/dc/dc_types.h |   6 +
 .../drm/amd/display/dc/dcn10/dcn10_dpp_cm.c   |   7 +
 .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.c |   8 +
 .../gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c  |  11 +
 .../drm/amd/display/dc/dcn21/dcn21_resource.c |   3 +
 drivers/gpu/drm/amd/display/dc/dm_services.h  |  14 +
 .../gpu/drm/amd/display/dc/inc/reg_helper.h   |  22 ++
 drivers/gpu/drm/amd/display/dc/os_types.h |   1 +
 15 files changed, 640 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h

diff --git a/drivers/gpu/drm/amd/display/dc/Makefile 
b/drivers/gpu/drm/amd/display/dc/Makefile
index a160512a2f04..6fe39f6392c7 100644
--- a/drivers/gpu/drm/amd/display/dc/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/Makefile
@@ -70,5 +70,9 @@ AMD_DM_REG_UPDATE = $(addprefix $(AMDDALPATH)/dc/,dc_helper.o)
 AMD_DISPLAY_FILES += $(AMD_DISPLAY_CORE)
 AMD_DISPLAY_FILES += $(AMD_DM_REG_UPDATE)
 
-
+ifdef CONFIG_DRM_AMD_DC_DMUB
+DC_DMUB += dc_dmub_srv.o
+AMD_DISPLAY_DMUB = $(addprefix $(AMDDALPATH)/dc/,$(DC_DMUB))
+AMD_DISPLAY_FILES += $(AMD_DISPLAY_DMUB)
+endif
 
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c 
b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
index bb2e8105e6ab..a3d890050e39 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
@@ -37,6 +37,10 @@
 #include "bios_parser_types_internal2.h"
 #include "amdgpu.h"
 
+#ifdef CONFIG_DRM_AMD_DC_DMUB
+#include "dc_dmub_srv.h"
+#include "dc.h"
+#endif
 
 #define DC_LOGGER \
bp->base.ctx->logger
@@ -103,6 +107,21 @@ static void init_dig_encoder_control(struct bios_parser 
*bp)
}
 }
 
+#ifdef CONFIG_DRM_AMD_DC_DMUB
+static void encoder_control_dmcub(
+   struct dc_dmub_srv *dmcub,
+   struct dig_encoder_stream_setup_parameters_v1_5 *dig)
+{
+   struct dmub_rb_cmd_digx_encoder_control encoder_control = { 0 };
+
+   encoder_control.header.type = DMUB_CMD__DIGX_ENCODER_CONTROL;
+   encoder_control.encoder_control.dig.stream_param = *dig;
+
+   dc_dmub_srv_cmd_queue(dmcub, _control.header);
+   dc_dmub_srv_cmd_execute(dmcub);
+   dc_dmub_srv_wait_idle(dmcub);
+}
+#endif
 static enum bp_result encoder_control_digx_v1_5(
struct bios_parser *bp,
struct bp_encoder_control *cntl)
@@ -154,6 +173,13 @@ static enum bp_result encoder_control_digx_v1_5(
default:
break;
}
+#ifdef CONFIG_DRM_AMD_DC_DMUB
+   if (bp->base.ctx->dc->ctx->dmub_srv &&
+   bp->base.ctx->dc->debug.dmub_command_table) {
+   encoder_control_dmcub(bp->base.ctx->dmub_srv, );
+   return BP_RESULT_OK;
+   }
+#endif
 
if (EXEC_BIOS_CMD_TABLE(digxencodercontrol, params))
result = BP_RESULT_OK;
@@ -190,7 +216,21 @@ static void init_transmitter_control(struct bios_parser 
*bp)
break;
}
 }
+#ifdef CONFIG_DRM_AMD_DC_DMUB
+static void transmitter_control_dmcub(
+   struct dc_dmub_srv *dmcub,
+   struct dig_transmitter_control_parameters_v1_6 *dig)
+{
+   struct dmub_rb_cmd_dig1_transmitter_control transmitter_control;
+
+   transmitter_control.header.type = DMUB_CMD__DIG1_TRANSMITTER_CONTROL;
+   transmitter_control.transmitter_control.dig = *dig;
 
+   dc_dmub_srv_cmd_queue(dmcub, _control.header);
+   dc_dmub_srv_cmd_execute(dmcub);
+   dc_dmub_srv_wait_idle(dmcub);
+}
+#endif
 static enum bp_result transmitter_control_v1_6(
struct bios_parser *bp,
struct bp_transmitter_control *cntl)
@@ -223,6 +263,14 @@ static enum bp_result transmitter_control_v1_6(
}
 
 
+#ifdef CONFIG_DRM_AMD_DC_DMUB
+   if (bp->base.ctx->dc->ctx->dmub_srv &&
+   bp->base.ctx->dc->debug.dmub_command_table) {
+   transmitter_control_dmcub(bp->base.ctx->dmub_srv, );
+   return BP_RESULT_OK;
+   }
+#endif
+
 /*color_depth not us

[PATCH 06/11] drm/amd/display: Add PSP FW version mask.

2019-10-28 Thread Nicholas Kazlauskas
From: Yongqiang Sun 

[Why]
PSP version format is AB.CD.EF.GH, where CD and GH is the main version.
current psp version check for dmcub loading dmcu check 0x00110029, in
case of some psp version eg: 0x00110227 which main version should be
0x00110027, will result in unexpeceted dmcub loading dmcu FW.

[How]
Add psp version mask 0x00FF00FF for checking version.

Signed-off-by: Yongqiang Sun 
Reviewed-by: Tony Cheng 
---
 drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c 
b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
index 3417100d51e4..3276944e6997 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
@@ -886,7 +886,7 @@ static void dcn21_dmcu_construct(
 
if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
psp_version = dm_read_reg(ctx, mmMP0_SMN_C2PMSG_58);
-   dmcu_dce->base.auto_load_dmcu = (psp_version > 0x00110029);
+   dmcu_dce->base.auto_load_dmcu = ((psp_version & 0x00FF00FF) > 
0x00110029);
dmcu_dce->base.psp_version = psp_version;
}
 }
-- 
2.20.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 11/11] drm/amd/display: Drop CONFIG_DRM_AMD_DC_DMUB guards

2019-10-28 Thread Nicholas Kazlauskas
[Why]
Support for DMUB only depends on support for DC. It doesn't use floating
point so we don't need to guard it by any specific DCN revision.

[How]
Drop the guards and cleanup the newlines around each one.

Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/Kconfig   |  6 -
 drivers/gpu/drm/amd/display/Makefile  | 12 +++--
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 20 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  4 ---
 drivers/gpu/drm/amd/display/dc/Makefile   |  3 ---
 .../drm/amd/display/dc/bios/command_table2.c  | 27 ++-
 drivers/gpu/drm/amd/display/dc/core/dc.c  |  6 +
 drivers/gpu/drm/amd/display/dc/dc.h   |  7 +
 drivers/gpu/drm/amd/display/dc/dc_helper.c| 22 +++
 drivers/gpu/drm/amd/display/dc/dc_types.h |  5 +---
 .../drm/amd/display/dc/dcn10/dcn10_dpp_cm.c   |  6 ++---
 .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.c |  5 +---
 .../gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c  |  5 +---
 .../drm/amd/display/dc/dcn21/dcn21_resource.c |  2 --
 drivers/gpu/drm/amd/display/dc/dm_services.h  |  4 ---
 .../gpu/drm/amd/display/dc/inc/reg_helper.h   |  3 ---
 drivers/gpu/drm/amd/display/dmub/src/Makefile |  2 --
 17 files changed, 22 insertions(+), 117 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/Kconfig 
b/drivers/gpu/drm/amd/display/Kconfig
index fced39e229d5..313183b80032 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -30,7 +30,6 @@ config DRM_AMD_DC_DCN2_1
bool "DCN 2.1 family"
depends on DRM_AMD_DC && X86
depends on DRM_AMD_DC_DCN2_0
-   select DRM_AMD_DC_DMUB
help
  Choose this option if you want to have
  Renoir support for display engine
@@ -53,11 +52,6 @@ config DRM_AMD_DC_HDCP
 if you want to support
 HDCP authentication
 
-config DRM_AMD_DC_DMUB
-def_bool n
-help
-  DMUB support for display engine
-
 config DEBUG_KERNEL_DC
bool "Enable kgdb break in DC"
depends on DRM_AMD_DC
diff --git a/drivers/gpu/drm/amd/display/Makefile 
b/drivers/gpu/drm/amd/display/Makefile
index 3c7332be4a89..2633de77de5e 100644
--- a/drivers/gpu/drm/amd/display/Makefile
+++ b/drivers/gpu/drm/amd/display/Makefile
@@ -34,27 +34,21 @@ subdir-ccflags-y += 
-I$(FULL_AMD_DISPLAY_PATH)/modules/freesync
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/info_packet
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/power
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dmub/inc
+
 ifdef CONFIG_DRM_AMD_DC_HDCP
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/hdcp
 endif
 
-ifdef CONFIG_DRM_AMD_DC_DMUB
-subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dmub/inc
-endif
-
 #TODO: remove when Timing Sync feature is complete
 subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0
 
-DAL_LIBS = amdgpu_dm dcmodules/freesync modules/color 
modules/info_packet modules/power
+DAL_LIBS = amdgpu_dm dcmodules/freesync modules/color 
modules/info_packet modules/power dmub/src
 
 ifdef CONFIG_DRM_AMD_DC_HDCP
 DAL_LIBS += modules/hdcp
 endif
 
-ifdef CONFIG_DRM_AMD_DC_DMUB
-DAL_LIBS += dmub/src
-endif
-
 AMD_DAL = $(addsuffix /Makefile, $(addprefix 
$(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS)))
 
 include $(AMD_DAL)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 920e84e40bbb..5fe0ed28eb01 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -30,12 +30,10 @@
 #include "dc.h"
 #include "dc/inc/core_types.h"
 #include "dal_asic_id.h"
-#ifdef CONFIG_DRM_AMD_DC_DMUB
 #include "dmub/inc/dmub_srv.h"
 #include "dc/inc/hw/dmcu.h"
 #include "dc/inc/hw/abm.h"
 #include "dc/dc_dmub_srv.h"
-#endif
 
 #include "vid.h"
 #include "amdgpu.h"
@@ -93,10 +91,9 @@
 #include "modules/power/power_helpers.h"
 #include "modules/inc/mod_info_packet.h"
 
-#ifdef CONFIG_DRM_AMD_DC_DMUB
 #define FIRMWARE_RENOIR_DMUB "amdgpu/renoir_dmcub.bin"
 MODULE_FIRMWARE(FIRMWARE_RENOIR_DMUB);
-#endif
+
 #define FIRMWARE_RAVEN_DMCU"amdgpu/raven_dmcu.bin"
 MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
 
@@ -677,7 +674,6 @@ void amdgpu_dm_audio_eld_notify(struct amdgpu_device *adev, 
int pin)
}
 }
 
-#ifdef CONFIG_DRM_AMD_DC_DMUB
 static int dm_dmub_hw_init(struct amdgpu_device *adev)
 {
const unsigned int psp_header_bytes = 0x100;
@@ -816,16 +812,13 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
return 0;
 }
 
-#endif
 static int amdgpu_dm_init(struct amdgpu_device *adev)
 {
struct dc_init_data init_data;
 #ifdef CONFIG_DRM_AMD_DC_HDCP
struct dc_callback_init init_params;

[PATCH 02/11] drm/amdgpu: Add PSP loading support for DMCUB ucode

2019-10-28 Thread Nicholas Kazlauskas
DMCUB ucode requires secure loading through PSP. This is already
supported in PSP as GFX_FW_TYPE_DMUB, it just needs to be mapped from
AMDGPU_UCODE_ID_DMCUB to GFX_FW_TYPE_DMUB.

DMUB is a shorthand name for DMCUB and can be used interchangeably.

Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index fd7a73f4fa70..d4cdd6fd3fbc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -1276,6 +1276,9 @@ static int psp_get_fw_type(struct amdgpu_firmware_info 
*ucode,
case AMDGPU_UCODE_ID_VCN1_RAM:
*type = GFX_FW_TYPE_VCN1_RAM;
break;
+   case AMDGPU_UCODE_ID_DMCUB:
+   *type = GFX_FW_TYPE_DMUB;
+   break;
case AMDGPU_UCODE_ID_MAXIMUM:
default:
return -EINVAL;
-- 
2.20.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 04/11] drm/amd/display: Add the DMUB service

2019-10-28 Thread Nicholas Kazlauskas
The DMUB service is the interface to the DMCUB.

It's required to support Renoir features so it will be enabled and
compiled automatically when the Renoir display engine is enabled via
CONFIG_DRM_AMD_DC_DCN2_1.

DMUB code will initially be guarded by CONFIG_DRM_AMD_DC_DMUB and later
switched to CONFIG_DRM_AMD_DC_DCN2_1 with the config option dropped.

Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/Kconfig   |   6 +
 drivers/gpu/drm/amd/display/Makefile  |   8 +
 .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   | 256 +
 .../gpu/drm/amd/display/dmub/inc/dmub_rb.h| 129 +
 .../gpu/drm/amd/display/dmub/inc/dmub_srv.h   | 505 ++
 .../amd/display/dmub/inc/dmub_trace_buffer.h  |  51 ++
 .../gpu/drm/amd/display/dmub/inc/dmub_types.h |  64 +++
 drivers/gpu/drm/amd/display/dmub/src/Makefile |  29 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn20.c | 137 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn20.h |  62 +++
 .../gpu/drm/amd/display/dmub/src/dmub_dcn21.c | 126 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn21.h |  45 ++
 .../gpu/drm/amd/display/dmub/src/dmub_reg.c   | 109 
 .../gpu/drm/amd/display/dmub/src/dmub_reg.h   | 120 +
 .../gpu/drm/amd/display/dmub/src/dmub_srv.c   | 415 ++
 15 files changed, 2062 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/inc/dmub_rb.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/inc/dmub_trace_buffer.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/inc/dmub_types.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/Makefile
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c

diff --git a/drivers/gpu/drm/amd/display/Kconfig 
b/drivers/gpu/drm/amd/display/Kconfig
index 313183b80032..fced39e229d5 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -30,6 +30,7 @@ config DRM_AMD_DC_DCN2_1
bool "DCN 2.1 family"
depends on DRM_AMD_DC && X86
depends on DRM_AMD_DC_DCN2_0
+   select DRM_AMD_DC_DMUB
help
  Choose this option if you want to have
  Renoir support for display engine
@@ -52,6 +53,11 @@ config DRM_AMD_DC_HDCP
 if you want to support
 HDCP authentication
 
+config DRM_AMD_DC_DMUB
+def_bool n
+help
+  DMUB support for display engine
+
 config DEBUG_KERNEL_DC
bool "Enable kgdb break in DC"
depends on DRM_AMD_DC
diff --git a/drivers/gpu/drm/amd/display/Makefile 
b/drivers/gpu/drm/amd/display/Makefile
index 36b3d6a5d04d..3c7332be4a89 100644
--- a/drivers/gpu/drm/amd/display/Makefile
+++ b/drivers/gpu/drm/amd/display/Makefile
@@ -38,6 +38,10 @@ ifdef CONFIG_DRM_AMD_DC_HDCP
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/hdcp
 endif
 
+ifdef CONFIG_DRM_AMD_DC_DMUB
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dmub/inc
+endif
+
 #TODO: remove when Timing Sync feature is complete
 subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0
 
@@ -47,6 +51,10 @@ ifdef CONFIG_DRM_AMD_DC_HDCP
 DAL_LIBS += modules/hdcp
 endif
 
+ifdef CONFIG_DRM_AMD_DC_DMUB
+DAL_LIBS += dmub/src
+endif
+
 AMD_DAL = $(addsuffix /Makefile, $(addprefix 
$(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS)))
 
 include $(AMD_DAL)
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h 
b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
new file mode 100644
index ..b25f92e3280d
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2019 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ 

[PATCH 03/11] drm/amd/display: Drop DMCUB from DCN21 resources

2019-10-28 Thread Nicholas Kazlauskas
The interface to the DMCUB won't be through DC itself. DC will instead
call into the DMUB interface introduced with a future change.

The CONFIG_DRM_AMD_DC_DMUB defines will still be used for now but will
be dropped at the end of the series.

Since this define was never configurable in the first place this code
wasn't used.

Signed-off-by: Nicholas Kazlauskas 
---
 .../drm/amd/display/dc/dcn21/dcn21_resource.c | 31 ---
 1 file changed, 31 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c 
b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
index 459bd9a5caed..1042197f1859 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
@@ -373,20 +373,6 @@ static const struct dce_abm_mask abm_mask = {
ABM_MASK_SH_LIST_DCN20(_MASK)
 };
 
-#ifdef CONFIG_DRM_AMD_DC_DMUB
-static const struct dcn21_dmcub_registers dmcub_regs = {
-   DMCUB_REG_LIST_DCN()
-};
-
-static const struct dcn21_dmcub_shift dmcub_shift = {
-   DMCUB_COMMON_MASK_SH_LIST_BASE(__SHIFT)
-};
-
-static const struct dcn21_dmcub_mask dmcub_mask = {
-   DMCUB_COMMON_MASK_SH_LIST_BASE(_MASK)
-};
-#endif
-
 #define audio_regs(id)\
 [id] = {\
AUD_COMMON_REG_LIST(id)\
@@ -970,11 +956,6 @@ static void destruct(struct dcn21_resource_pool *pool)
if (pool->base.dmcu != NULL)
dce_dmcu_destroy(>base.dmcu);
 
-#ifdef CONFIG_DRM_AMD_DC_DMUB
-   if (pool->base.dmcub != NULL)
-   dcn21_dmcub_destroy(>base.dmcub);
-#endif
-
if (pool->base.dccg != NULL)
dcn_dccg_destroy(>base.dccg);
 
@@ -1766,18 +1747,6 @@ static bool construct(
goto create_fail;
}
 
-#ifdef CONFIG_DRM_AMD_DC_DMUB
-   pool->base.dmcub = dcn21_dmcub_create(ctx,
-   _regs,
-   _shift,
-   _mask);
-   if (pool->base.dmcub == NULL) {
-   dm_error("DC: failed to create dmcub!\n");
-   BREAK_TO_DEBUGGER();
-   goto create_fail;
-   }
-#endif
-
pool->base.pp_smu = dcn21_pp_smu_create(ctx);
 
num_pipes = dcn2_1_ip.max_num_dpp;
-- 
2.20.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 07/11] drm/amd/display: Hook up the DMUB service in DM

2019-10-28 Thread Nicholas Kazlauskas
[Why]
We need DMCUB on Renoir to support DMCU and PHY initialization.
The DMUB service provides a mechanism to load the DMCUB.

[How]
Include the DMUB service in amdgpu_dm.

Frontdoor loading of the DMCUB firmware needs to happen via PSP. To
pass the firmware to PSP we need to hand it off to the firmware list
in the base driver during software initialization.

Most of the DMUB service can technically be initialized at this point
in time, but we don't want to be allocating framebuffer memory for
hardware that doesn't support the DMCUB and in order to check that we
need to be able to read registers - something DM helpers aren't setup
to do in software initialization.

So everything but the service creation itself will get deferred to
hardware initialization.

Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 267 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  50 
 2 files changed, 317 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 48f5b43e2698..230fd0155463 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -30,6 +30,11 @@
 #include "dc.h"
 #include "dc/inc/core_types.h"
 #include "dal_asic_id.h"
+#ifdef CONFIG_DRM_AMD_DC_DMUB
+#include "dmub/inc/dmub_srv.h"
+#include "dc/inc/hw/dmcu.h"
+#include "dc/inc/hw/abm.h"
+#endif
 
 #include "vid.h"
 #include "amdgpu.h"
@@ -87,6 +92,10 @@
 #include "modules/power/power_helpers.h"
 #include "modules/inc/mod_info_packet.h"
 
+#ifdef CONFIG_DRM_AMD_DC_DMUB
+#define FIRMWARE_RENOIR_DMUB "amdgpu/renoir_dmcub.bin"
+MODULE_FIRMWARE(FIRMWARE_RENOIR_DMUB);
+#endif
 #define FIRMWARE_RAVEN_DMCU"amdgpu/raven_dmcu.bin"
 MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
 
@@ -667,12 +676,149 @@ void amdgpu_dm_audio_eld_notify(struct amdgpu_device 
*adev, int pin)
}
 }
 
+#ifdef CONFIG_DRM_AMD_DC_DMUB
+static int dm_dmub_hw_init(struct amdgpu_device *adev)
+{
+   const unsigned int psp_header_bytes = 0x100;
+   const unsigned int psp_footer_bytes = 0x100;
+   const struct dmcub_firmware_header_v1_0 *hdr;
+   struct dmub_srv *dmub_srv = adev->dm.dmub_srv;
+   const struct firmware *dmub_fw = adev->dm.dmub_fw;
+   struct dmcu *dmcu = adev->dm.dc->res_pool->dmcu;
+   struct abm *abm = adev->dm.dc->res_pool->abm;
+   struct dmub_srv_region_params region_params;
+   struct dmub_srv_region_info region_info;
+   struct dmub_srv_fb_params fb_params;
+   struct dmub_srv_fb_info fb_info;
+   struct dmub_srv_hw_params hw_params;
+   enum dmub_status status;
+   const unsigned char *fw_inst_const, *fw_bss_data;
+   uint32_t i;
+   int r;
+   bool has_hw_support;
+
+   if (!dmub_srv)
+   /* DMUB isn't supported on the ASIC. */
+   return 0;
+
+   if (!dmub_fw) {
+   /* Firmware required for DMUB support. */
+   DRM_ERROR("No firmware provided for DMUB.\n");
+   return -EINVAL;
+   }
+
+   status = dmub_srv_has_hw_support(dmub_srv, _hw_support);
+   if (status != DMUB_STATUS_OK) {
+   DRM_ERROR("Error checking HW support for DMUB: %d\n", status);
+   return -EINVAL;
+   }
+
+   if (!has_hw_support) {
+   DRM_INFO("DMUB unsupported on ASIC\n");
+   return 0;
+   }
+
+   hdr = (const struct dmcub_firmware_header_v1_0 *)dmub_fw->data;
+
+   /* Calculate the size of all the regions for the DMUB service. */
+   memset(_params, 0, sizeof(region_params));
+
+   region_params.inst_const_size = le32_to_cpu(hdr->inst_const_bytes) -
+   psp_header_bytes - psp_footer_bytes;
+   region_params.bss_data_size = le32_to_cpu(hdr->bss_data_bytes);
+   region_params.vbios_size = adev->dm.dc->ctx->dc_bios->bios_size;
+
+   status = dmub_srv_calc_region_info(dmub_srv, _params,
+  _info);
+
+   if (status != DMUB_STATUS_OK) {
+   DRM_ERROR("Error calculating DMUB region info: %d\n", status);
+   return -EINVAL;
+   }
+
+   /*
+* Allocate a framebuffer based on the total size of all the regions.
+* TODO: Move this into GART.
+*/
+   r = amdgpu_bo_create_kernel(adev, region_info.fb_size, PAGE_SIZE,
+   AMDGPU_GEM_DOMAIN_VRAM, >dm.dmub_bo,
+   >dm.dmub_bo_gpu_addr,
+   >dm.dmub_bo_cpu_addr);
+   if (r)
+   return r;
+
+   /* Rebase the regions on the framebuffer address. */
+   memset(_params, 

[PATCH 00/11] Add DMCUB support for Renoir

2019-10-28 Thread Nicholas Kazlauskas
The DMCUB is the Display MicroController Unit B, a display microcontroller
that is required for Renoir to support realtime display features
(ABM, PSR) and display hardware initialization.

This patch series adds the required firmware loading support in amdgpu
and the DMUB service support for amdgpu_dm and dc to interface with the
DMCUB.

The term DMCUB will generally refer to the actual microcontroller while
DMUB will generally refer to the software interface.

Cc: Harry Wentland 

Nicholas Kazlauskas (9):
  drm/amdgpu: Add ucode support for DMCUB
  drm/amdgpu: Add PSP loading support for DMCUB ucode
  drm/amd/display: Drop DMCUB from DCN21 resources
  drm/amd/display: Add the DMUB service
  drm/amd/display: Hook up the DMUB service in DM
  drm/amdgpu: Add DMCUB to firmware query interface
  drm/amd/display: Add DMUB support to DC
  drm/amd/display: Register DMUB service with DC
  drm/amd/display: Drop CONFIG_DRM_AMD_DC_DMUB guards

Yongqiang Sun (2):
  drm/amd/display: Change dmcu init sequence for dmcub loading dmcu FW.
  drm/amd/display: Add PSP FW version mask.

 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c   |  12 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c   |   3 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c |  11 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h |   9 +
 drivers/gpu/drm/amd/display/Makefile  |   4 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 261 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  46 ++
 drivers/gpu/drm/amd/display/dc/Makefile   |   5 +-
 .../drm/amd/display/dc/bios/command_table2.c  |  80 +++
 drivers/gpu/drm/amd/display/dc/core/dc.c  |   4 +
 drivers/gpu/drm/amd/display/dc/dc.h   |   7 +
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c  | 119 +
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h  |  60 +++
 drivers/gpu/drm/amd/display/dc/dc_helper.c| 257 +
 drivers/gpu/drm/amd/display/dc/dc_types.h |   3 +
 drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c |  79 +++
 drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h |  13 +
 .../drm/amd/display/dc/dcn10/dcn10_dpp_cm.c   |   5 +
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c |   2 +-
 .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.c |   5 +
 .../gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c  |   8 +
 .../drm/amd/display/dc/dcn21/dcn21_resource.c |  36 +-
 drivers/gpu/drm/amd/display/dc/dm_services.h  |  10 +
 drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h  |   2 +
 .../gpu/drm/amd/display/dc/inc/reg_helper.h   |  19 +
 drivers/gpu/drm/amd/display/dc/os_types.h |   1 +
 .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   | 256 +
 .../gpu/drm/amd/display/dmub/inc/dmub_rb.h| 129 +
 .../gpu/drm/amd/display/dmub/inc/dmub_srv.h   | 505 ++
 .../amd/display/dmub/inc/dmub_trace_buffer.h  |  51 ++
 .../gpu/drm/amd/display/dmub/inc/dmub_types.h |  64 +++
 drivers/gpu/drm/amd/display/dmub/src/Makefile |  27 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn20.c | 137 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn20.h |  62 +++
 .../gpu/drm/amd/display/dmub/src/dmub_dcn21.c | 126 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn21.h |  45 ++
 .../gpu/drm/amd/display/dmub/src/dmub_reg.c   | 109 
 .../gpu/drm/amd/display/dmub/src/dmub_reg.h   | 120 +
 .../gpu/drm/amd/display/dmub/src/dmub_srv.c   | 415 ++
 include/uapi/drm/amdgpu_drm.h |   3 +
 40 files changed, 3072 insertions(+), 38 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/inc/dmub_rb.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/inc/dmub_trace_buffer.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/inc/dmub_types.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/Makefile
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c

-- 
2.20.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Free gamma after calculating legacy transfer function

2019-10-11 Thread Nicholas Kazlauskas
[Why]
We're leaking memory by not freeing the gamma used to calculate the
transfer function for legacy gamma.

[How]
Release the gamma after we're done with it.

Cc: Philip Yang 
Cc: Harry Wentland 
Cc: Bhawanpreet Lakha 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index b43bb7f90e4e..2233d293a707 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -210,6 +210,8 @@ static int __set_legacy_tf(struct dc_transfer_func *func,
res = mod_color_calculate_regamma_params(func, gamma, true, has_rom,
 NULL);
 
+   dc_gamma_release();
+
return res ? 0 : -ENOMEM;
 }
 
-- 
2.20.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Make plane z-pos explicit to userspace

2019-10-03 Thread Nicholas Kazlauskas
[Why]
Many userspace assumes that the DRM plane index indicates the plane
z-order, with a lower index being lower depth and a higher index being
higher depth. This is currently what we assume in DM.

DRM has a zpos plane property to make this explicit to userspace and
there are clients that make use of this information.

[How]
Attach the immutable zpos property to the plane.

While we can technically order the planes in any manner since we
virtualize them in DC we don't currently have the software support.

The z-pos could potentially become immutable later but for now
just let userspace do the ordering.

Cc: Leo Li 
Cc: Harry Wentland 
Cc: Rodrigo Siqueira 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 239b1ae86007..e58b0b7e3c52 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4897,6 +4897,9 @@ static int amdgpu_dm_plane_init(struct 
amdgpu_display_manager *dm,
if (res)
return res;
 
+   /* Make z-pos of each plane explicit - lower ID is lower depth */
+   drm_plane_create_zpos_immutable_property(plane, plane->index);
+
if (plane->type == DRM_PLANE_TYPE_OVERLAY &&
plane_cap && plane_cap->per_pixel_alpha) {
unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
-- 
2.20.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Calculate bpc based on max_requested_bpc

2019-08-21 Thread Nicholas Kazlauskas
[Why]
The only place where state->max_bpc is updated on the connector is
at the start of atomic check during drm_atomic_connector_check. It
isn't updated when adding the connectors to the atomic state after
the fact. It also doesn't necessarily reflect the right value when
called in amdgpu during mode validation outside of atomic check.

This can cause the wrong bpc to be used even if the max_requested_bpc
is the correct value.

[How]
Don't rely on state->max_bpc reflecting the real bpc value and just
do the min(...) based on display info bpc and max_requested_bpc.

Cc: David Francis 
Cc: Bhawanpreet Lakha 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c| 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 7cf8dbccce95..73ed7b6bd8d3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3216,13 +3216,25 @@ static enum dc_color_depth
 convert_color_depth_from_display_info(const struct drm_connector *connector,
  const struct drm_connector_state *state)
 {
-   uint32_t bpc = connector->display_info.bpc;
+   uint8_t bpc = (uint8_t)connector->display_info.bpc;
+
+   /* Assume 8 bpc by default if no bpc is specified. */
+   bpc = bpc ? bpc : 8;
 
if (!state)
state = connector->state;
 
if (state) {
-   bpc = state->max_bpc;
+   /*
+* Cap display bpc based on the user requested value.
+*
+* The value for state->max_bpc may not correctly updated
+* depending on when the connector gets added to the state
+* or if this was called outside of atomic check, so it
+* can't be used directly.
+*/
+   bpc = min(bpc, state->max_requested_bpc);
+
/* Round down to the nearest even number. */
bpc = bpc - (bpc & 1);
}
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 4/4] drm/amd/display: Lock the CRTC when setting CRC source

2019-08-20 Thread Nicholas Kazlauskas
[Why]
We need to ensure that we're holding the lock on the CRTC when setting
the CRC source since we're modifying the CRTC state directly.

We also need to wait for any outstanding non-blocking commits to finish
so they aren't reading state that's potentially being modified -
non-blocking commits don't hold the CRTC lock while doing commit tail
work.

[How]
Lock the CRTC using its mutex. While holding the lock check if there's
any commit active on the CRTC - if there is, it's non-blocking and
we should wait until it's finished by waiting for hw_done to be
signaled since that's the last point where we touch CRTC state.

Cc: David Francis 
Cc: Bhawanpreet Lakha 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 63 +++
 1 file changed, 51 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index e9d5b1fad625..fa86b9e706af 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -135,13 +135,13 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc 
*crtc,
 
 int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
 {
-   struct dm_crtc_state *crtc_state = to_dm_crtc_state(crtc->state);
+   enum amdgpu_dm_pipe_crc_source source = dm_parse_crc_source(src_name);
+   struct drm_crtc_commit *commit;
+   struct dm_crtc_state *crtc_state;
struct drm_dp_aux *aux = NULL;
bool enable = false;
bool enabled = false;
-   int ret;
-
-   enum amdgpu_dm_pipe_crc_source source = dm_parse_crc_source(src_name);
+   int ret = 0;
 
if (source < 0) {
DRM_DEBUG_DRIVER("Unknown CRC source %s for CRTC%d\n",
@@ -149,7 +149,33 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, 
const char *src_name)
return -EINVAL;
}
 
+   ret = drm_modeset_lock(>mutex, NULL);
+   if (ret)
+   return ret;
+
+   spin_lock(>commit_lock);
+   commit = list_first_entry_or_null(>commit_list,
+ struct drm_crtc_commit, commit_entry);
+   if (commit)
+   drm_crtc_commit_get(commit);
+   spin_unlock(>commit_lock);
+
+   if (commit) {
+   /*
+* Need to wait for all outstanding programming to complete
+* in commit tail since it can modify CRC related fields and
+* hardware state. Since we're holding the CRTC lock we're
+* guaranteed that no other commit work can be queued off
+* before we modify the state below.
+*/
+   ret = wait_for_completion_interruptible_timeout(
+   >hw_done, 10 * HZ);
+   if (ret)
+   goto cleanup;
+   }
+
enable = amdgpu_dm_is_valid_crc_source(source);
+   crtc_state = to_dm_crtc_state(crtc->state);
 
/*
 * USER REQ SRC | CURRENT SRC | BEHAVIOR
@@ -183,19 +209,23 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, 
const char *src_name)
 
if (!aconn) {
DRM_DEBUG_DRIVER("No amd connector matching CRTC-%d\n", 
crtc->index);
-   return -EINVAL;
+   ret = -EINVAL;
+   goto cleanup;
}
 
aux = >dm_dp_aux.aux;
 
if (!aux) {
DRM_DEBUG_DRIVER("No dp aux for amd connector\n");
-   return -EINVAL;
+   ret = -EINVAL;
+   goto cleanup;
}
}
 
-   if (amdgpu_dm_crtc_configure_crc_source(crtc, crtc_state, source))
-   return -EINVAL;
+   if (amdgpu_dm_crtc_configure_crc_source(crtc, crtc_state, source)) {
+   ret = -EINVAL;
+   goto cleanup;
+   }
 
/*
 * Reading the CRC requires the vblank interrupt handler to be
@@ -205,12 +235,13 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, 
const char *src_name)
if (!enabled && enable) {
ret = drm_crtc_vblank_get(crtc);
if (ret)
-   return ret;
+   goto cleanup;
 
if (dm_is_crc_source_dprx(source)) {
if (drm_dp_start_crc(aux, crtc)) {
DRM_DEBUG_DRIVER("dp start crc failed\n");
-   return -EINVAL;
+   ret = -EINVAL;
+   goto cleanup;
}
}
} else if (enabled && !enable) {
@@ -218,7 +249,8 @@ int amdgpu_dm_crtc_set_crc_source(struct d

[PATCH 1/4] drm/amd/display: Check return code for CRC drm_crtc_vblank_get

2019-08-20 Thread Nicholas Kazlauskas
[Why]
The call to drm_crtc_vblank_get can fail if vblank is disabled and
we try to increment the reference.

Since drm_crtc_vblank_get internally drops the reference when it fails
it means the subsequent drm_crtc_vblank_put(...) when closing the file
drops a zero reference.

This was found via igt@kms_plane@pixel-format-pipe-A-planes.

[How]
Check the return code and return it on failure.

We wouldn't have been able to enable CRC reading anyway since vblank
wasn't enabled.

Cc: David Francis 
Cc: Bhawanpreet Lakha 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index b01256a4692e..f675626ef56b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -105,6 +105,7 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, 
const char *src_name)
struct drm_dp_aux *aux = NULL;
bool enable = false;
bool enabled = false;
+   int ret;
 
enum amdgpu_dm_pipe_crc_source source = dm_parse_crc_source(src_name);
 
@@ -175,7 +176,10 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, 
const char *src_name)
 */
enabled = amdgpu_dm_is_valid_crc_source(crtc_state->crc_src);
if (!enabled && enable) {
-   drm_crtc_vblank_get(crtc);
+   ret = drm_crtc_vblank_get(crtc);
+   if (ret)
+   return ret;
+
if (dm_is_crc_source_dprx(source)) {
if (drm_dp_start_crc(aux, crtc)) {
DRM_DEBUG_DRIVER("dp start crc failed\n");
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 2/4] drm/amd/display: Use connector list for finding DPRX CRC aux

2019-08-20 Thread Nicholas Kazlauskas
[Why]
This change is a refactor in preparation for adding locking and removing
the requirement for a stream state on the CRTC for enabling CRC capture
to fix igt@kms_plane_multiple@* warnings.

[How]
We can get the aux by finding the matching connector for the CRTC
with the assumption that we're not doing cloning.

Cc: David Francis 
Cc: Bhawanpreet Lakha 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 19 +++
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index f675626ef56b..c57ff8821fe2 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -101,7 +101,6 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, 
const char *src_name)
struct amdgpu_device *adev = crtc->dev->dev_private;
struct dm_crtc_state *crtc_state = to_dm_crtc_state(crtc->state);
struct dc_stream_state *stream_state = crtc_state->stream;
-   struct amdgpu_dm_connector *aconn;
struct drm_dp_aux *aux = NULL;
bool enable = false;
bool enabled = false;
@@ -137,9 +136,21 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, 
const char *src_name)
 * DPRX DITHER  | | Enable DPRX CRC, need 'aux', set dither
 */
if (dm_is_crc_source_dprx(source) ||
-   (source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE &&
-dm_is_crc_source_dprx(crtc_state->crc_src))) {
-   aconn = stream_state->link->priv;
+   (source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE &&
+dm_is_crc_source_dprx(crtc_state->crc_src))) {
+   struct amdgpu_dm_connector *aconn = NULL;
+   struct drm_connector *connector;
+   struct drm_connector_list_iter conn_iter;
+
+   drm_connector_list_iter_begin(crtc->dev, _iter);
+   drm_for_each_connector_iter (connector, _iter) {
+   if (!connector->state || connector->state->crtc != crtc)
+   continue;
+
+   aconn = to_amdgpu_dm_connector(connector);
+   break;
+   }
+   drm_connector_list_iter_end(_iter);
 
if (!aconn) {
DRM_DEBUG_DRIVER("No amd connector matching CRTC-%d\n", 
crtc->index);
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 3/4] drm/amd/display: Split out DC programming for CRC capture

2019-08-20 Thread Nicholas Kazlauskas
[Why]
Calling amdgpu_dm_crtc_set_crc_source in amdgpu_dm directly has the
consequence of adding additional vblank references or starting DPRX
CRC capture more than once without calling stop first.

Vblank references for CRC capture should be managed entirely by opening
and closing the CRC file from userspace.

Stream state also shouldn't be required on the CRC so we can close the
file after the CRTC has been disabled.

[How]
Do DC programming required for configuring CRC capture separately from
setting the source. Whenever we re-enable or reset a CRC this
programming should be reapplied.

CRC vblank reference handling in amdgpu_dm can be entirely dropped after
this.

Stream state also no longer needs to be required since we can just defer
the programming to when the stream is actually enabled.

Cc: David Francis 
Cc: Bhawanpreet Lakha 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 ++--
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 62 ---
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h |  6 ++
 3 files changed, 49 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 911fe78b47c1..7cf8dbccce95 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5967,11 +5967,9 @@ static void amdgpu_dm_enable_crtc_interrupts(struct 
drm_device *dev,
/* The stream has changed so CRC capture needs to re-enabled. */
source = dm_new_crtc_state->crc_src;
if (amdgpu_dm_is_valid_crc_source(source)) {
-   dm_new_crtc_state->crc_src = 
AMDGPU_DM_PIPE_CRC_SOURCE_NONE;
-   if (source == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC)
-   amdgpu_dm_crtc_set_crc_source(crtc, "crtc");
-   else if (source == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX)
-   amdgpu_dm_crtc_set_crc_source(crtc, "dprx");
+   amdgpu_dm_crtc_configure_crc_source(
+   crtc, dm_new_crtc_state,
+   dm_new_crtc_state->crc_src);
}
 #endif
}
@@ -6022,23 +6020,8 @@ static int amdgpu_dm_atomic_commit(struct drm_device 
*dev,
 
if (dm_old_crtc_state->interrupts_enabled &&
(!dm_new_crtc_state->interrupts_enabled ||
-drm_atomic_crtc_needs_modeset(new_crtc_state))) {
-   /*
-* Drop the extra vblank reference added by CRC
-* capture if applicable.
-*/
-   if 
(amdgpu_dm_is_valid_crc_source(dm_new_crtc_state->crc_src))
-   drm_crtc_vblank_put(crtc);
-
-   /*
-* Only keep CRC capture enabled if there's
-* still a stream for the CRTC.
-*/
-   if (!dm_new_crtc_state->stream)
-   dm_new_crtc_state->crc_src = 
AMDGPU_DM_PIPE_CRC_SOURCE_NONE;
-
+drm_atomic_crtc_needs_modeset(new_crtc_state)))
manage_dm_interrupts(adev, acrtc, false);
-   }
}
/*
 * Add check here for SoC's that support hardware cursor plane, to
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index c57ff8821fe2..e9d5b1fad625 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -96,11 +96,46 @@ amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc, 
const char *src_name,
return 0;
 }
 
-int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
+int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
+   struct dm_crtc_state *dm_crtc_state,
+   enum amdgpu_dm_pipe_crc_source source)
 {
struct amdgpu_device *adev = crtc->dev->dev_private;
+   struct dc_stream_state *stream_state = dm_crtc_state->stream;
+   bool enable = amdgpu_dm_is_valid_crc_source(source);
+   int ret = 0;
+
+   /* Configuration will be deferred to stream enable. */
+   if (!stream_state)
+   return 0;
+
+   mutex_lock(>dm.dc_lock);
+
+   /* Enable CRTC CRC generation if necessary. */
+   if (dm_is_crc_source_crtc(source)) {
+   if (!dc_stream_configure_crc(stream_state->ctx->dc,
+stream_state, enable, enable)) {
+   ret = -EINVAL;
+   goto unlock;
+   }
+   }
+
+ 

[PATCH 2/2] drm/amd/display: Block immediate flips for non-fast updates

2019-08-02 Thread Nicholas Kazlauskas
[Why]
Underflow can occur in the case where we change buffer pitch, DCC state,
rotation or mirroring for a plane while also performing an immediate
flip. It can also generate a p-state warning stack trace on DCN1 which
is typically observed during the cursor handler pipe locking because of
how frequent cursor updates can occur.

[How]
Store the update type on each CRTC - every plane will have access to
the CRTC state if it's flipping. If the update type is not
UPDATE_TYPE_FAST then the immediate flip should be disallowed.

No changes to the target vblank sequencing need to be done, we just
need to ensure that the surface registers do a double buffered update.

Cc: David Francis 
Cc: Bhawanpreet Lakha 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c| 16 +++-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h|  1 +
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index ffb3c7247ac6..e941d0d3794b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5690,8 +5690,14 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
bundle->surface_updates[planes_count].plane_info =
>plane_infos[planes_count];
 
+   /*
+* Only allow immediate flips for fast updates that don't
+* change FB pitch, DCC state, rotation or mirroing.
+*/
bundle->flip_addrs[planes_count].flip_immediate =
-   (crtc->state->pageflip_flags & 
DRM_MODE_PAGE_FLIP_ASYNC) != 0;
+   (crtc->state->pageflip_flags &
+DRM_MODE_PAGE_FLIP_ASYNC) != 0 &&
+   acrtc_state->update_type == UPDATE_TYPE_FAST;
 
timestamp_ns = ktime_get_ns();
bundle->flip_addrs[planes_count].flip_timestamp_in_us = 
div_u64(timestamp_ns, 1000);
@@ -7311,6 +7317,14 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
state->async_update = !drm_atomic_helper_async_check(dev, 
state);
}
 
+   /* Store the overall update type for use later in atomic check. */
+   for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) {
+   struct dm_crtc_state *dm_new_crtc_state =
+   to_dm_crtc_state(new_crtc_state);
+
+   dm_new_crtc_state->update_type = (int)overall_update_type;
+   }
+
/* Must be success */
WARN_ON(ret);
return ret;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index da48a857949f..cbd6608f58e6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -307,6 +307,7 @@ struct dm_crtc_state {
bool cm_has_degamma;
bool cm_is_degamma_srgb;
 
+   int update_type;
int active_planes;
bool interrupts_enabled;
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 1/2] drm/amd/display: Validate dc_plane_info and dc_plane_size in atomic check

2019-08-02 Thread Nicholas Kazlauskas
[Why]
Pitch, DCC, rotation and mirroring can result in updates that are not
UPDATE_TYPE_FAST but UPDATE_TYPE_MED instead. DC needs dc_plane_info
and dc_plane_size to make this determination and we aren't currently
passing this into DC during atomic check.

Underflow (visible or non-visible) can occur if we don't validate this
correctly. This also will generally trigger p-state warnings, typically
via the cursor handler when locking.

[How]
Get the framebuffer tiling flags and generate the required structures
for DC in dm_determine_update_type_for_commit.

Cc: David Francis 
Cc: Bhawanpreet Lakha 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 24 +++
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 040169180a63..ffb3c7247ac6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6987,6 +6987,12 @@ dm_determine_update_type_for_commit(struct 
amdgpu_display_manager *dm,
continue;
 
for_each_oldnew_plane_in_state(state, plane, old_plane_state, 
new_plane_state, j) {
+   const struct amdgpu_framebuffer *amdgpu_fb =
+   to_amdgpu_framebuffer(new_plane_state->fb);
+   struct dc_plane_info plane_info;
+   struct dc_flip_addrs flip_addr;
+   uint64_t tiling_flags;
+
new_plane_crtc = new_plane_state->crtc;
old_plane_crtc = old_plane_state->crtc;
new_dm_plane_state = to_dm_plane_state(new_plane_state);
@@ -7030,6 +7036,24 @@ dm_determine_update_type_for_commit(struct 
amdgpu_display_manager *dm,
 
updates[num_plane].scaling_info = _info;
 
+   if (amdgpu_fb) {
+   ret = get_fb_info(amdgpu_fb, _flags);
+   if (ret)
+   goto cleanup;
+
+   memset(_addr, 0, sizeof(flip_addr));
+
+   ret = fill_dc_plane_info_and_addr(
+   dm->adev, new_plane_state, tiling_flags,
+   _info,
+   _addr.address);
+   if (ret)
+   goto cleanup;
+
+   updates[num_plane].plane_info = _info;
+   updates[num_plane].flip_addr = _addr;
+   }
+
num_plane++;
}
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 2/3] drm/amd/display: Skip determining update type for async updates

2019-07-31 Thread Nicholas Kazlauskas
[Why]
By passing through the dm_determine_update_type_for_commit for atomic
commits that can be done asynchronously we are incurring a
performance penalty by locking access to the global private object
and holding that access until the end of the programming sequence.

This is also allocating a new large dc_state on every access in addition
to retaining all the references on each stream and plane until the end
of the programming sequence.

[How]
Shift the determination for async update before validation. Return early
if it's going to be an async update.

Cc: Leo Li 
Cc: David Francis 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 27 ++-
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 2efb0eadf602..4c90662e9fa2 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7216,6 +7216,26 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
if (ret)
goto fail;
 
+   if (state->legacy_cursor_update) {
+   /*
+* This is a fast cursor update coming from the plane update
+* helper, check if it can be done asynchronously for better
+* performance.
+*/
+   state->async_update =
+   !drm_atomic_helper_async_check(dev, state);
+
+   /*
+* Skip the remaining global validation if this is an async
+* update. Cursor updates can be done without affecting
+* state or bandwidth calcs and this avoids the performance
+* penalty of locking the private state object and
+* allocating a new dc_state.
+*/
+   if (state->async_update)
+   return 0;
+   }
+
/* Check scaling and underscan changes*/
/* TODO Removed scaling changes validation due to inability to commit
 * new stream into context w\o causing full reset. Need to
@@ -7268,13 +7288,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
ret = -EINVAL;
goto fail;
}
-   } else if (state->legacy_cursor_update) {
-   /*
-* This is a fast cursor update coming from the plane update
-* helper, check if it can be done asynchronously for better
-* performance.
-*/
-   state->async_update = !drm_atomic_helper_async_check(dev, 
state);
}
 
/* Must be success */
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 3/3] drm/amd/display: Don't replace the dc_state for fast updates

2019-07-31 Thread Nicholas Kazlauskas
[Why]
DRM private objects have no hw_done/flip_done fencing mechanism on their
own and cannot be used to sequence commits accordingly.

When issuing commits that don't touch the same set of hardware resources
like page-flips on different CRTCs we can run into the issue below
because of this:

1. Client requests non-blocking Commit #1, has a new dc_state #1,
state is swapped, commit tail is deferred to work queue

2. Client requests non-blocking Commit #2, has a new dc_state #2,
state is swapped, commit tail is deferred to work queue

3. Commit #2 work starts, commit tail finishes,
atomic state is cleared, dc_state #1 is freed

4. Commit #1 work starts,
commit tail encounters null pointer deref on dc_state #1

In order to change the DC state as in the private object we need to
ensure that we wait for all outstanding commits to finish and that
any other pending commits must wait for the current one to finish as
well.

We do this for MEDIUM and FULL updates. But not for FAST updates, nor
would we want to since it would cause stuttering from the delays.

FAST updates that go through dm_determine_update_type_for_commit always
create a new dc_state and lock the DRM private object if there are
any changed planes.

We need the old state to validate, but we don't actually need the new
state here.

[How]
If the commit isn't a full update then the use after free can be
resolved by simply discarding the new state entirely and retaining
the existing one instead.

With this change the sequence above can be reexamined. Commit #2 will
still free Commit #1's reference, but before this happens we actually
added an additional reference as part of Commit #2.

If an update comes in during this that needs to change the dc_state
it will need to wait on Commit #1 and Commit #2 to finish. Then it'll
swap the state, finish the work in commit tail and drop the last
reference on Commit #2's dc_state.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=204181
Cc: Leo Li 
Cc: David Francis 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 4c90662e9fa2..fe5291b16193 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7288,6 +7288,29 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
ret = -EINVAL;
goto fail;
}
+   } else {
+   /*
+* The commit is a fast update. Fast updates shouldn't change
+* the DC context, affect global validation, and can have their
+* commit work done in parallel with other commits not touching
+* the same resource. If we have a new DC context as part of
+* the DM atomic state from validation we need to free it and
+* retain the existing one instead.
+*/
+   struct dm_atomic_state *new_dm_state, *old_dm_state;
+
+   new_dm_state = dm_atomic_get_new_state(state);
+   old_dm_state = dm_atomic_get_old_state(state);
+
+   if (new_dm_state && old_dm_state) {
+   if (new_dm_state->context)
+   dc_release_state(new_dm_state->context);
+
+   new_dm_state->context = old_dm_state->context;
+
+   if (old_dm_state->context)
+   dc_retain_state(old_dm_state->context);
+   }
}
 
/* Must be success */
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 1/3] drm/amd/display: Allow cursor async updates for framebuffer swaps

2019-07-31 Thread Nicholas Kazlauskas
[Why]
We previously allowed framebuffer swaps as async updates for cursor
planes but had to disable them due to a bug in DRM with async update
handling and incorrect ref counting. The check to block framebuffer
swaps has been added to DRM for a while now, so this check is redundant.

The real fix that allows this to properly in DRM has also finally been
merged and is getting backported into stable branches, so dropping
this now seems to be the right time to do so.

[How]
Drop the redundant check for old_fb != new_fb.

With the proper fix in DRM, this should also fix some cursor stuttering
issues with xf86-video-amdgpu since it double buffers the cursor.

IGT tests that swap framebuffers (-varying-size for example) should
also pass again.

Cc: Leo Li 
Cc: David Francis 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 --
 1 file changed, 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 040169180a63..2efb0eadf602 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4504,20 +4504,10 @@ static int dm_plane_atomic_check(struct drm_plane 
*plane,
 static int dm_plane_atomic_async_check(struct drm_plane *plane,
   struct drm_plane_state *new_plane_state)
 {
-   struct drm_plane_state *old_plane_state =
-   drm_atomic_get_old_plane_state(new_plane_state->state, plane);
-
/* Only support async updates on cursor planes. */
if (plane->type != DRM_PLANE_TYPE_CURSOR)
return -EINVAL;
 
-   /*
-* DRM calls prepare_fb and cleanup_fb on new_plane_state for
-* async commits so don't allow fb changes.
-*/
-   if (old_plane_state->fb != new_plane_state->fb)
-   return -EINVAL;
-
return 0;
 }
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 1/2] drm/amd/display: Embed DCN2 SOC bounding box

2019-07-30 Thread Nicholas Kazlauskas
[Why]
In order to support uclk switching on NV10 the SOC bounding box
needs to be updated.

[How]
We currently read the constants from the gpu info FW, but supporting
workarounds in DC for different versions of the FW adds additional
complexity to the codebase.

NV10 has been released so it's cleanest to keep the bounding box and
source code in sync by embedding the bounding box like we do for
other ASICs.

Fixes: 02316e963a5a ("drm/amd/display: Force uclk to max for every state")

Cc: Alex Deucher 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 .../drm/amd/display/dc/dcn20/dcn20_resource.c | 114 +-
 1 file changed, 112 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
index 44537651f0a1..ff30f5cc4981 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -80,7 +80,7 @@
 
 #include "amdgpu_socbb.h"
 
-#define SOC_BOUNDING_BOX_VALID false
+#define SOC_BOUNDING_BOX_VALID true
 #define DC_LOGGER_INIT(logger)
 
 struct _vcs_dpi_ip_params_st dcn2_0_ip = {
@@ -154,7 +154,117 @@ struct _vcs_dpi_ip_params_st dcn2_0_ip = {
.xfc_fill_constant_bytes = 0,
 };
 
-struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc = { 0 };
+struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc = {
+   /* Defaults that get patched on driver load from firmware. */
+   .clock_limits = {
+   {
+   .state = 0,
+   .dcfclk_mhz = 560.0,
+   .fabricclk_mhz = 560.0,
+   .dispclk_mhz = 513.0,
+   .dppclk_mhz = 513.0,
+   .phyclk_mhz = 540.0,
+   .socclk_mhz = 560.0,
+   .dscclk_mhz = 171.0,
+   .dram_speed_mts = 8960.0,
+   },
+   {
+   .state = 1,
+   .dcfclk_mhz = 694.0,
+   .fabricclk_mhz = 694.0,
+   .dispclk_mhz = 642.0,
+   .dppclk_mhz = 642.0,
+   .phyclk_mhz = 600.0,
+   .socclk_mhz = 694.0,
+   .dscclk_mhz = 214.0,
+   .dram_speed_mts = 11104.0,
+   },
+   {
+   .state = 2,
+   .dcfclk_mhz = 875.0,
+   .fabricclk_mhz = 875.0,
+   .dispclk_mhz = 734.0,
+   .dppclk_mhz = 734.0,
+   .phyclk_mhz = 810.0,
+   .socclk_mhz = 875.0,
+   .dscclk_mhz = 245.0,
+   .dram_speed_mts = 14000.0,
+   },
+   {
+   .state = 3,
+   .dcfclk_mhz = 1000.0,
+   .fabricclk_mhz = 1000.0,
+   .dispclk_mhz = 1100.0,
+   .dppclk_mhz = 1100.0,
+   .phyclk_mhz = 810.0,
+   .socclk_mhz = 1000.0,
+   .dscclk_mhz = 367.0,
+   .dram_speed_mts = 16000.0,
+   },
+   {
+   .state = 4,
+   .dcfclk_mhz = 1200.0,
+   .fabricclk_mhz = 1200.0,
+   .dispclk_mhz = 1284.0,
+   .dppclk_mhz = 1284.0,
+   .phyclk_mhz = 810.0,
+   .socclk_mhz = 1200.0,
+   .dscclk_mhz = 428.0,
+   .dram_speed_mts = 16000.0,
+   },
+   /*Extra state, no dispclk ramping*/
+   {
+   .state = 5,
+   .dcfclk_mhz = 1200.0,
+   .fabricclk_mhz = 1200.0,
+   .dispclk_mhz = 1284.0,
+   .dppclk_mhz = 1284.0,
+   .phyclk_mhz = 810.0,
+   .socclk_mhz = 1200.0,
+   .dscclk_mhz = 428.0,
+   .dram_speed_mts = 16000.0,
+   },
+   },
+   .num_states = 5,
+   .sr_exit_time_us = 8.6,
+   .sr_enter_plus_exit_time_us = 10.9,
+   .urgent_latency_us = 4.0,
+   .urgent_latency_pixe

[PATCH 1/2] drm/amd/display: Expose audio inst from DC to DM

2019-07-09 Thread Nicholas Kazlauskas
[Why]
In order to give pin notifications to the sound driver from DM we need
to know whether audio is enabled on a stream and what pin it's using
from DC.

[How]
Expose the instance via stream status if it's a mapped resource for
the stream. It will be -1 if there's no audio mapped.

Cc: Leo Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +++
 drivers/gpu/drm/amd/display/dc/dc_stream.h| 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index d10ebfd33a60..5b85139fb3ce 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -2008,6 +2008,9 @@ enum dc_status resource_map_pool_resources(
if (context->streams[i] == stream) {
context->stream_status[i].primary_otg_inst = 
pipe_ctx->stream_res.tg->inst;
context->stream_status[i].stream_enc_inst = 
pipe_ctx->stream_res.stream_enc->id;
+   context->stream_status[i].audio_inst =
+   pipe_ctx->stream_res.audio ? 
pipe_ctx->stream_res.audio->inst : -1;
+
return DC_OK;
}
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h 
b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index e253a5c591f6..0fa1c26bc20d 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -42,6 +42,7 @@ struct dc_stream_status {
int primary_otg_inst;
int stream_enc_inst;
int plane_count;
+   int audio_inst;
struct timing_sync_info timing_sync_info;
struct dc_plane_state *plane_states[MAX_SURFACE_NUM];
 };
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 2/2] drm/amd/display: Add drm_audio_component support to amdgpu_dm

2019-07-09 Thread Nicholas Kazlauskas
[Why]
The drm_audio_component can be used to give pin ELD notifications
directly to the sound driver. This fixes audio endpoints disappearing
due to missing unsolicited notifications.

[How]
Send the notification via the audio component whenever we enable or
disable audio state on a stream. This matches what i915 does with
their drm_audio_component and what Takashi Iwai's proposed hack for
radeon/amdpgu did.

This is a bit delayed in when the notification actually occurs, however.
We wait until after all the programming is complete rather than sending
the notification mid sequence.

Particular care is needed for the get ELD callback since it can happen
outside the locking and fencing DRM does for atomic commits.

Cc: Takashi Iwai 
Cc: Leo Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 222 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  25 ++
 2 files changed, 247 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f26c7b348aa9..9ef785497eb5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -55,6 +55,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -63,6 +64,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 #include "ivsrcid/dcn/irqsrcs_dcn_1_0.h"
@@ -506,6 +508,139 @@ static void amdgpu_dm_fbc_init(struct drm_connector 
*connector)
 
 }
 
+static int amdgpu_dm_audio_component_get_eld(struct device *kdev, int port,
+ int pipe, bool *enabled,
+ unsigned char *buf, int max_bytes)
+{
+   struct drm_device *dev = dev_get_drvdata(kdev);
+   struct amdgpu_device *adev = dev->dev_private;
+   struct drm_connector *connector;
+   struct drm_connector_list_iter conn_iter;
+   struct amdgpu_dm_connector *aconnector;
+   int ret = 0;
+
+   *enabled = false;
+
+   mutex_lock(>dm.audio_lock);
+
+   drm_connector_list_iter_begin(dev, _iter);
+   drm_for_each_connector_iter(connector, _iter) {
+   aconnector = to_amdgpu_dm_connector(connector);
+   if (aconnector->audio_inst != port)
+   continue;
+
+   *enabled = true;
+   ret = drm_eld_size(connector->eld);
+   memcpy(buf, connector->eld, min(max_bytes, ret));
+
+   break;
+   }
+   drm_connector_list_iter_end(_iter);
+
+   mutex_unlock(>dm.audio_lock);
+
+   DRM_DEBUG_KMS("Get ELD : idx=%d ret=%d en=%d\n", port, ret, *enabled);
+
+   return ret;
+}
+
+static const struct drm_audio_component_ops amdgpu_dm_audio_component_ops = {
+   .get_eld = amdgpu_dm_audio_component_get_eld,
+};
+
+static int amdgpu_dm_audio_component_bind(struct device *kdev,
+  struct device *hda_kdev, void *data)
+{
+   struct drm_device *dev = dev_get_drvdata(kdev);
+   struct amdgpu_device *adev = dev->dev_private;
+   struct drm_audio_component *acomp = data;
+
+   acomp->ops = _dm_audio_component_ops;
+   acomp->dev = kdev;
+   adev->dm.audio_component = acomp;
+
+   return 0;
+}
+
+static void amdgpu_dm_audio_component_unbind(struct device *kdev,
+ struct device *hda_kdev, void *data)
+{
+   struct drm_device *dev = dev_get_drvdata(kdev);
+   struct amdgpu_device *adev = dev->dev_private;
+   struct drm_audio_component *acomp = data;
+
+   acomp->ops = NULL;
+   acomp->dev = NULL;
+   adev->dm.audio_component = NULL;
+}
+
+static const struct component_ops amdgpu_dm_audio_component_bind_ops = {
+   .bind   = amdgpu_dm_audio_component_bind,
+   .unbind = amdgpu_dm_audio_component_unbind,
+};
+
+static int amdgpu_dm_audio_init(struct amdgpu_device *adev)
+{
+   int i, ret;
+
+   if (!amdgpu_audio)
+   return 0;
+
+   adev->mode_info.audio.enabled = true;
+
+   adev->mode_info.audio.num_pins = adev->dm.dc->res_pool->audio_count;
+
+   for (i = 0; i < adev->mode_info.audio.num_pins; i++) {
+   adev->mode_info.audio.pin[i].channels = -1;
+   adev->mode_info.audio.pin[i].rate = -1;
+   adev->mode_info.audio.pin[i].bits_per_sample = -1;
+   adev->mode_info.audio.pin[i].status_bits = 0;
+   adev->mode_info.audio.pin[i].category_code = 0;
+   adev->mode_info.audio.pin[i].connected = false;
+   adev->mode_info.audio.pin[i].id =
+   adev->dm.dc->res_pool->audios[i]->inst;
+   adev->mode_info.audio.pin[i].offset = 0;
+   }
+
+   ret = component_add(adev->dev, 

[PATCH v2] drm/amd/display: update infoframe after dig fe is turned on (v2)

2019-06-24 Thread Nicholas Kazlauskas
[Why]
The AVI infoframe is incorrectly programmed on DCN1/2 when enabling a
stream - causing the wrong pixel encoding to be used for display.

This is because the AVI infoframe is programmed before the DIG BE is
connected to the FE and turned on, so enabling the AFMT block doesn't
actually work and the registers subsequently can't be written to.

[How]
Program the infoframe *after* turning on the DIG FE. This was the
behavior previously used but it was incorrectly reverted
when adding the DCN2 HW sequencer code.

v2: Don't call update_info_frame twice

Fixes: 54ff35915948 ("drm/amd/display: Add DCN2 HW Sequencer and Resource")

Cc: Harry Wentland 
Cc: Roman Li 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 940e74b7d2c6..84d90b475e2a 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -686,6 +686,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
dmdata_dp : 
dmdata_hdmi);
}
 #endif
+   dce110_update_info_frame(pipe_ctx);
 
/* enable early control to avoid corruption on DP monitor*/
active_total_with_borders =
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: update infoframe after dig fe is turned on (v2)

2019-06-24 Thread Nicholas Kazlauskas
[Why]
The AVI infoframe is incorrectly programmed on DCN1/2 when enabling a
stream - causing the wrong pixel encoding to be used for display.

This is because the AVI infoframe is programmed before the DIG BE is
connected to the FE and turned on, so enabling the AFMT block doesn't
actually work and the registers subsequently can't be written to.

[How]
Program the infoframe *after* turning on the DIG FE. This was the
behavior previously used but it was incorrectly reverted
when adding the DCN2 HW sequencer code.

Fixes: 54ff35915948 ("drm/amd/display: Add DCN2 HW Sequencer and Resource")

Cc: Harry Wentland 
Cc: Roman Li 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 940e74b7d2c6..b4b8ded16e22 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -666,6 +666,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
 
/* update AVI info frame (HDMI, DP)*/
/* TODO: FPGA may change to hwss.update_info_frame */
+   dce110_update_info_frame(pipe_ctx);
 
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata != 
NULL &&
@@ -686,6 +687,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
dmdata_dp : 
dmdata_hdmi);
}
 #endif
+   dce110_update_info_frame(pipe_ctx);
 
/* enable early control to avoid corruption on DP monitor*/
active_total_with_borders =
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] Revert "drm/amd/display: Enable fast plane updates when state->allow_modeset = true"

2019-06-20 Thread Nicholas Kazlauskas
This reverts commit ebc8c6f18322ad54275997a888ca1731d74b711f.

There are still missing corner cases with cursor interaction and these
fast plane updates on Picasso and Raven2 leading to endless PSTATE
warnings for typical desktop usage depending on the userspace.

This change should be reverted until these issues have been resolved.

Cc: David Francis 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 33dcd4187157..d6acbcfa570c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6471,6 +6471,14 @@ static bool should_reset_plane(struct drm_atomic_state 
*state,
struct drm_crtc_state *new_crtc_state;
int i;
 
+   /*
+* TODO: Remove this hack once the checks below are sufficient
+* enough to determine when we need to reset all the planes on
+* the stream.
+*/
+   if (state->allow_modeset)
+   return true;
+
/* Exit early if we know that we're adding or removing the plane. */
if (old_plane_state->crtc != new_plane_state->crtc)
return true;
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Allow cursor async updates for framebuffer swaps

2019-06-10 Thread Nicholas Kazlauskas
[Why]
We previously allowed framebuffer swaps as async updates for cursor
planes but had to disable them due to a bug in DRM with async update
handling and incorrect ref counting. The check to block framebuffer
swaps has been added to DRM for a while now, so this check is redundant.

The real fix that allows this to properly in DRM has also finally been
merged and is getting backported into stable branches, so dropping
this now seems to be the right time to do so.

[How]
Drop the redundant check for old_fb != new_fb.

With the proper fix in DRM, this should also fix some cursor stuttering
issues with xf86-video-amdgpu since it double buffers the cursor.

IGT tests that swap framebuffers (-varying-size for example) should
also pass again.

Cc: David Francis 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 --
 1 file changed, 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 45f0d5b6c468..100b2c60ff1c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4315,20 +4315,10 @@ static int dm_plane_atomic_check(struct drm_plane 
*plane,
 static int dm_plane_atomic_async_check(struct drm_plane *plane,
   struct drm_plane_state *new_plane_state)
 {
-   struct drm_plane_state *old_plane_state =
-   drm_atomic_get_old_plane_state(new_plane_state->state, plane);
-
/* Only support async updates on cursor planes. */
if (plane->type != DRM_PLANE_TYPE_CURSOR)
return -EINVAL;
 
-   /*
-* DRM calls prepare_fb and cleanup_fb on new_plane_state for
-* async commits so don't allow fb changes.
-*/
-   if (old_plane_state->fb != new_plane_state->fb)
-   return -EINVAL;
-
return 0;
 }
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Enable fast plane updates when state->allow_modeset = true

2019-06-07 Thread Nicholas Kazlauskas
[Why]
Whenever the a modeset is allowed (but not neccessarily required) we
currently recreate all the planes in the state. Most IGT tests and
legacy IOCTLs create atomic commits with this flag set, so the pipes
are often unnecessarily reprogrammed.

Poor performance and stuttering can occur when many of these commits
are frequently issued.

This flag was needed when the appropriate conditions for checking
whether the planes needed a reset were not in place, but
should_reset_plane should cover everything needed now.

[How]
Drop the check for state->allow_modeset in should_reset_plane.

All planes on a CRTC should reset in the following conditions:
- The CRTC needs a modeset
- The CRTC degamma changes
- Planes are added or removed to the CRTC

These conditions are all covered in should_reset_plane.

We still can't drop the format change check in should_reset_plane since
fill_dc_plane_info_and_addr isn't called when validating the state, so
we can't tell if a FULL update is needed or not.

Cc: David Francis 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 
 1 file changed, 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index a698c8f272ed..45f0d5b6c468 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6446,14 +6446,6 @@ static bool should_reset_plane(struct drm_atomic_state 
*state,
struct drm_crtc_state *new_crtc_state;
int i;
 
-   /*
-* TODO: Remove this hack once the checks below are sufficient
-* enough to determine when we need to reset all the planes on
-* the stream.
-*/
-   if (state->allow_modeset)
-   return true;
-
/* Exit early if we know that we're adding or removing the plane. */
if (old_plane_state->crtc != new_plane_state->crtc)
return true;
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 2/2] drm/amd/display: Set default ABM level to module parameter

2019-06-06 Thread Nicholas Kazlauskas
[Why]
The module parameter to specify the default ABM level is now defined,
so hook it up in DM.

[How]
On connector reset specify the default level. DC will program this as
part of the modeset since it gets passed onto the stream in
dm_update_crtc_state.

It's only set for eDP connectors, but it doesn't matter if this is
specified for connectors or hardware that doesn't support ABM.

It's DC's responsibility to check that ABM can be set or adjusted, and
DC does check that the DMCU firmware is running and if there's backlight
control available.

Cc: Harry Wentland 
Cc: David Francis 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index a698c8f272ed..f0c216d78a07 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3821,6 +3821,9 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector 
*connector)
state->underscan_hborder = 0;
state->underscan_vborder = 0;
 
+   if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+   state->abm_level = amdgpu_dm_abm_level;
+
__drm_atomic_helper_connector_reset(connector, >base);
}
 }
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 1/2] drm/amd/amdgpu: Add module parameter for specifying default ABM level

2019-06-06 Thread Nicholas Kazlauskas
[Why]
It's non trivial to configure or specify an ABM reduction level for
userspace outside of X. There is also no method to specify the default
ABM value at boot time.

A parameter should be added to configure this.

[How]
Expose a module parameter that can specify the default ABM level to
use for eDP connectors on DC enabled hardware that loads the DMCU
firmware.

The default is still disabled (0), but levels can range from 1-4. Levels
control how much the backlight can be reduced, with being the least
amount of reduction and four being the most reduction.

Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 16 
 2 files changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 19a00282e34c..4beb26738e1e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -155,6 +155,7 @@ extern int amdgpu_gpu_recovery;
 extern int amdgpu_emu_mode;
 extern uint amdgpu_smu_memory_pool_size;
 extern uint amdgpu_dc_feature_mask;
+extern uint amdgpu_dm_abm_level;
 extern struct amdgpu_mgpu_info mgpu_info;
 extern int amdgpu_ras_enable;
 extern uint amdgpu_ras_mask;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 1f38d6fc1fe3..dde53f8e230b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -686,6 +686,22 @@ MODULE_PARM_DESC(hws_gws_support, "MEC FW support gws 
barriers (false = not supp
 MODULE_PARM_DESC(dcfeaturemask, "all stable DC features enabled (default))");
 module_param_named(dcfeaturemask, amdgpu_dc_feature_mask, uint, 0444);
 
+/**
+ * DOC: abmlevel (uint)
+ * Override the default ABM (Adaptive Backlight Management) level used for DC
+ * enabled hardware. Requires DMCU to be supported and loaded.
+ * Valid levels are 0-4. A value of 0 indicates that ABM should be disabled by
+ * default. Values 1-4 control the maximum allowable brightness reduction via
+ * the ABM algorithm, with 1 being the least reduction and 4 being the most
+ * reduction.
+ *
+ * Defaults to 0, or disabled. Userspace can still override this level later
+ * after boot.
+ */
+uint amdgpu_dm_abm_level = 0;
+MODULE_PARM_DESC(abmlevel, "ABM level (0 = off (default), 1-4 = backlight 
reduction level) ");
+module_param_named(abmlevel, amdgpu_dm_abm_level, uint, 0444);
+
 static const struct pci_device_id pciidlist[] = {
 #ifdef  CONFIG_DRM_AMDGPU_SI
{0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Use current connector state if NULL when checking bpc

2019-06-05 Thread Nicholas Kazlauskas
[Why]
The old logic for checking which output depth to use relied on using
the current connector state rather than the new proposed state. This
was a problem when performing atomic commits since we weren't verifying
it against the incoming max_requested_bpc.

But switching this to only use the new state and not the current state
breaks filtering modes - it'll always assume that the maximum bpc
supported by the display is in use, which will cause certain modes
like 1440p@144Hz to be filtered even when using 8bpc.

[How]
Still use the connector->state if we aren't passed an explicit state.
This will respect the max_bpc the user currently has when filtering
modes.

Also remember to reset the default max_requested_bpc to 8 whenever
connector reset is called to retain old behavior when using the new
property.

Cc: Harry Wentland 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index a698c8f272ed..f627c17a1039 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3046,6 +3046,9 @@ convert_color_depth_from_display_info(const struct 
drm_connector *connector,
 {
uint32_t bpc = connector->display_info.bpc;
 
+   if (!state)
+   state = connector->state;
+
if (state) {
bpc = state->max_bpc;
/* Round down to the nearest even number. */
@@ -3820,6 +3823,7 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector 
*connector)
state->underscan_enable = false;
state->underscan_hborder = 0;
state->underscan_vborder = 0;
+   state->base.max_requested_bpc = 8;
 
__drm_atomic_helper_connector_reset(connector, >base);
}
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Always allocate initial connector state state

2019-06-04 Thread Nicholas Kazlauskas
[Why]
Unlike our regular connectors, MST connectors don't start off with
an initial connector state. This causes a NULL pointer dereference to
occur when attaching the bpc property since it tries to modify the
connector state.

We need an initial connector state on the connector to avoid the crash.

[How]
Use our reset helper to allocate an initial state and reset the values
to their defaults. We were already doing this before, just not for
MST connectors.

Cc: Leo Li 
Cc: Roman Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index a698c8f272ed..4523ab100bc3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4743,6 +4743,13 @@ void amdgpu_dm_connector_init_helper(struct 
amdgpu_display_manager *dm,
 {
struct amdgpu_device *adev = dm->ddev->dev_private;
 
+   /*
+* Some of the properties below require access to state, like bpc.
+* Allocate some default initial connector state with our reset helper.
+*/
+   if (aconnector->base.funcs->reset)
+   aconnector->base.funcs->reset(>base);
+
aconnector->connector_id = link_index;
aconnector->dc_link = link;
aconnector->base.interlace_allowed = false;
@@ -4932,9 +4939,6 @@ static int amdgpu_dm_connector_init(struct 
amdgpu_display_manager *dm,
>base,
_dm_connector_helper_funcs);
 
-   if (aconnector->base.funcs->reset)
-   aconnector->base.funcs->reset(>base);
-
amdgpu_dm_connector_init_helper(
dm,
aconnector,
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2] drm/amd/display: Add connector debugfs for "output_bpc"

2019-06-03 Thread Nicholas Kazlauskas
[Why]
This will be useful for verifying whether we enter the correct output
color depth from IGT.

[How]
Locks the connector and associated CRTC if available and outputs
the current and maximum output bpc values.

Example:

cat /sys/kernel/debug/dri/0/DP-1/output_bpc
Current: 8
Maximum: 10

v2: Drop unneeded connector status check

Cc: Leo Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 71 ++-
 1 file changed, 69 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 1d5fc5ad3bee..a3e362fa6747 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -672,6 +672,71 @@ static ssize_t dp_phy_test_pattern_debugfs_write(struct 
file *f, const char __us
return bytes_from_user;
 }
 
+/*
+ * Returns the current and maximum output bpc for the connector.
+ * Example usage: cat /sys/kernel/debug/dri/0/DP-1/output_bpc
+ */
+static int output_bpc_show(struct seq_file *m, void *data)
+{
+   struct drm_connector *connector = m->private;
+   struct drm_device *dev = connector->dev;
+   struct drm_crtc *crtc = NULL;
+   struct dm_crtc_state *dm_crtc_state = NULL;
+   int res = -ENODEV;
+   unsigned int bpc;
+
+   mutex_lock(>mode_config.mutex);
+   drm_modeset_lock(>mode_config.connection_mutex, NULL);
+
+   if (connector->state == NULL)
+   goto unlock;
+
+   crtc = connector->state->crtc;
+   if (crtc == NULL)
+   goto unlock;
+
+   drm_modeset_lock(>mutex, NULL);
+   if (crtc->state == NULL)
+   goto unlock;
+
+   dm_crtc_state = to_dm_crtc_state(crtc->state);
+   if (dm_crtc_state->stream == NULL)
+   goto unlock;
+
+   switch (dm_crtc_state->stream->timing.display_color_depth) {
+   case COLOR_DEPTH_666:
+   bpc = 6;
+   break;
+   case COLOR_DEPTH_888:
+   bpc = 8;
+   break;
+   case COLOR_DEPTH_101010:
+   bpc = 10;
+   break;
+   case COLOR_DEPTH_121212:
+   bpc = 12;
+   break;
+   case COLOR_DEPTH_161616:
+   bpc = 16;
+   break;
+   default:
+   goto unlock;
+   }
+
+   seq_printf(m, "Current: %u\n", bpc);
+   seq_printf(m, "Maximum: %u\n", connector->display_info.bpc);
+   res = 0;
+
+unlock:
+   if (crtc)
+   drm_modeset_unlock(>mutex);
+
+   drm_modeset_unlock(>mode_config.connection_mutex);
+   mutex_unlock(>mode_config.mutex);
+
+   return res;
+}
+
 /*
  * Returns the min and max vrr vfreq through the connector's debugfs file.
  * Example usage: cat /sys/kernel/debug/dri/0/DP-1/vrr_range
@@ -730,8 +795,6 @@ static ssize_t dp_sdp_message_debugfs_write(struct file *f, 
const char __user *b
return write_size;
 }
 
-DEFINE_SHOW_ATTRIBUTE(vrr_range);
-
 static ssize_t dp_dpcd_address_write(struct file *f, const char __user *buf,
 size_t size, loff_t *pos)
 {
@@ -814,6 +877,9 @@ static ssize_t dp_dpcd_data_read(struct file *f, char 
__user *buf,
return read_size - r;
 }
 
+DEFINE_SHOW_ATTRIBUTE(output_bpc);
+DEFINE_SHOW_ATTRIBUTE(vrr_range);
+
 static const struct file_operations dp_link_settings_debugfs_fops = {
.owner = THIS_MODULE,
.read = dp_link_settings_read,
@@ -866,6 +932,7 @@ static const struct {
{"link_settings", _link_settings_debugfs_fops},
{"phy_settings", _phy_settings_debugfs_fop},
{"test_pattern", _phy_test_pattern_fops},
+   {"output_bpc", _bpc_fops},
{"vrr_range", _range_fops},
{"sdp_message", _message_fops},
{"aux_dpcd_address", _dpcd_address_debugfs_fops},
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Add connector debugfs for "output_bpc"

2019-06-03 Thread Nicholas Kazlauskas
[Why]
This will be useful for verifying whether we enter the correct output
color depth from IGT.

[How]
Locks the connector and associated CRTC if available and outputs
the current and maximum output bpc values.

Example:

cat /sys/kernel/debug/dri/0/DP-1/output_bpc
Current: 8
Maximum: 10

Change-Id: Ic881c0c729c5444b80256ccfe55ac52cec345388
Cc: Leo Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 74 ++-
 1 file changed, 72 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 1d5fc5ad3bee..0de86a7e31b5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -672,6 +672,74 @@ static ssize_t dp_phy_test_pattern_debugfs_write(struct 
file *f, const char __us
return bytes_from_user;
 }
 
+/*
+ * Returns the current and maximum output bpc for the connector.
+ * Example usage: cat /sys/kernel/debug/dri/0/DP-1/output_bpc
+ */
+static int output_bpc_show(struct seq_file *m, void *data)
+{
+   struct drm_connector *connector = m->private;
+   struct drm_device *dev = connector->dev;
+   struct drm_crtc *crtc = NULL;
+   struct dm_crtc_state *dm_crtc_state = NULL;
+   int res = -ENODEV;
+   unsigned int bpc;
+
+   mutex_lock(>mode_config.mutex);
+   drm_modeset_lock(>mode_config.connection_mutex, NULL);
+
+   if (connector->state == NULL)
+   goto unlock;
+
+   crtc = connector->state->crtc;
+   if (crtc == NULL)
+   goto unlock;
+
+   drm_modeset_lock(>mutex, NULL);
+   if (crtc->state == NULL)
+   goto unlock;
+
+   dm_crtc_state = to_dm_crtc_state(crtc->state);
+   if (dm_crtc_state->stream == NULL)
+   goto unlock;
+
+   if (connector->status != connector_status_connected)
+   return -ENODEV;
+
+   switch (dm_crtc_state->stream->timing.display_color_depth) {
+   case COLOR_DEPTH_666:
+   bpc = 6;
+   break;
+   case COLOR_DEPTH_888:
+   bpc = 8;
+   break;
+   case COLOR_DEPTH_101010:
+   bpc = 10;
+   break;
+   case COLOR_DEPTH_121212:
+   bpc = 12;
+   break;
+   case COLOR_DEPTH_161616:
+   bpc = 16;
+   break;
+   default:
+   goto unlock;
+   }
+
+   seq_printf(m, "Current: %u\n", bpc);
+   seq_printf(m, "Maximum: %u\n", connector->display_info.bpc);
+   res = 0;
+
+unlock:
+   if (crtc)
+   drm_modeset_unlock(>mutex);
+
+   drm_modeset_unlock(>mode_config.connection_mutex);
+   mutex_unlock(>mode_config.mutex);
+
+   return res;
+}
+
 /*
  * Returns the min and max vrr vfreq through the connector's debugfs file.
  * Example usage: cat /sys/kernel/debug/dri/0/DP-1/vrr_range
@@ -730,8 +798,6 @@ static ssize_t dp_sdp_message_debugfs_write(struct file *f, 
const char __user *b
return write_size;
 }
 
-DEFINE_SHOW_ATTRIBUTE(vrr_range);
-
 static ssize_t dp_dpcd_address_write(struct file *f, const char __user *buf,
 size_t size, loff_t *pos)
 {
@@ -814,6 +880,9 @@ static ssize_t dp_dpcd_data_read(struct file *f, char 
__user *buf,
return read_size - r;
 }
 
+DEFINE_SHOW_ATTRIBUTE(output_bpc);
+DEFINE_SHOW_ATTRIBUTE(vrr_range);
+
 static const struct file_operations dp_link_settings_debugfs_fops = {
.owner = THIS_MODULE,
.read = dp_link_settings_read,
@@ -866,6 +935,7 @@ static const struct {
{"link_settings", _link_settings_debugfs_fops},
{"phy_settings", _phy_settings_debugfs_fop},
{"test_pattern", _phy_test_pattern_fops},
+   {"output_bpc", _bpc_fops},
{"vrr_range", _range_fops},
{"sdp_message", _message_fops},
{"aux_dpcd_address", _dpcd_address_debugfs_fops},
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Add back missing hw translate init for DCN1_01

2019-05-31 Thread Nicholas Kazlauskas
[Why]
DCN_VERSION_1_01 is no longer handled in the dal_hw_translate_init
switch since it was inadvertently dropped in the patch that removed the
unnecessary DCN1_01 guards.

This caused numerous regressions on DCN1_01 when loading the driver.

[How]
Add it back.

Cc: Harry Wentland 
Fixes: 97df424fe7a7 ("drm/amd/display: Drop DCN1_01 guards")
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c 
b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
index 77615146b96e..1f9833dc8cfe 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
@@ -81,6 +81,7 @@ bool dal_hw_translate_init(
return true;
 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
case DCN_VERSION_1_0:
+   case DCN_VERSION_1_01:
dal_hw_translate_dcn10_init(translate);
return true;
 #endif
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Don't set mode_changed=false if the stream was removed

2019-05-30 Thread Nicholas Kazlauskas
[Why]
When switching from vt to desktop with EDID emulation we can receive
an atomic commit such that we have a crtc where mode_changed = true.

During the dm_update_crtc_state disable pass we remove the stream from
the context and free it on the dm_new_crtc_state.

During the enable pass we compare the new provisional stream to the
dm_old_crtc_state->stream and determine that the stream is unchanged
and no scaling has been changed.

Following this, new_crtc_state->mode_changed is then set to false.
The connectors haven't changed and the CRTC active state hasn't changed
so drm_atomic_crtc_needs_modeset returns false, so we jump to
skip_modeset and we hit:

BUG_ON(dm_new_crtc_state->stream == NULL);

...since the old stream is gone from the context and the new stream is
also still NULL.

[How]
Ensure that we still a stream to reuse before checking if we can reuse
the old stream without a full modeset.

Cc: Roman Li 
Cc: Leo Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 57359037ed7c..796f83ca7a4c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6248,7 +6248,17 @@ static int dm_update_crtc_state(struct 
amdgpu_display_manager *dm,
 
dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
 
-   if (dc_is_stream_unchanged(new_stream, 
dm_old_crtc_state->stream) &&
+   /*
+* If we already removed the old stream from the context
+* (and set the new stream to NULL) then we can't reuse
+* the old stream even if the stream and scaling are unchanged.
+* We'll hit the BUG_ON and black screen.
+*
+* TODO: Refactor this function to allow this check to work
+* in all conditions.
+*/
+   if (dm_new_crtc_state->stream &&
+   dc_is_stream_unchanged(new_stream, 
dm_old_crtc_state->stream) &&
dc_is_stream_scaling_unchanged(new_stream, 
dm_old_crtc_state->stream)) {
new_crtc_state->mode_changed = false;
DRM_DEBUG_DRIVER("Mode change not required, setting 
mode_changed to %d",
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 0/2] drm/amd/display: Add HDR output metadata support for amdgpu

2019-05-28 Thread Nicholas Kazlauskas
This patch series enables HDR output metadata support in amdgpu using the
DRM HDR interface merged in drm-misc-next. Enabled for DCE and DCN ASICs
over DP and HDMI.

It's limited to static HDR metadata support for now since that's all the
DRM interface supports. It requires a modeset for entering and exiting HDR
but the metadata can be changed without one.

Cc: Harry Wentland 

Nicholas Kazlauskas (2):
  drm/amd/display: Expose HDR output metadata for supported connectors
  drm/amd/display: Only force modesets when toggling HDR

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 155 +-
 1 file changed, 151 insertions(+), 4 deletions(-)

-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 1/2] drm/amd/display: Expose HDR output metadata for supported connectors

2019-05-28 Thread Nicholas Kazlauskas
[Why]
For userspace to send static HDR metadata to the display we need to
attach the property on the connector and send it to DC.

[How]
The property is attached to HDMI and DP connectors. Since the metadata
isn't actually available when creating the connector this isn't a
property we can dynamically support based on the extension block
being available or not.

When the HDR metadata is changed a modeset will be forced for now.
We need to switch from 8bpc to 10bpc in most cases anyway, and we want
to fully exit HDR mode when userspace gives us a NULL metadata, so this
isn't completely unnecessary.

The requirement can later be reduced to just entering and exiting HDR
or switching max bpc.

Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 125 ++
 1 file changed, 125 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 995f9df66142..eb31acca7ed6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3871,6 +3871,121 @@ enum drm_mode_status 
amdgpu_dm_connector_mode_valid(struct drm_connector *connec
return result;
 }
 
+static int fill_hdr_info_packet(const struct drm_connector_state *state,
+   struct dc_info_packet *out)
+{
+   struct hdmi_drm_infoframe frame;
+   unsigned char buf[30]; /* 26 + 4 */
+   ssize_t len;
+   int ret, i;
+
+   memset(out, 0, sizeof(*out));
+
+   if (!state->hdr_output_metadata)
+   return 0;
+
+   ret = drm_hdmi_infoframe_set_hdr_metadata(, state);
+   if (ret)
+   return ret;
+
+   len = hdmi_drm_infoframe_pack_only(, buf, sizeof(buf));
+   if (len < 0)
+   return (int)len;
+
+   /* Static metadata is a fixed 26 bytes + 4 byte header. */
+   if (len != 30)
+   return -EINVAL;
+
+   /* Prepare the infopacket for DC. */
+   switch (state->connector->connector_type) {
+   case DRM_MODE_CONNECTOR_HDMIA:
+   out->hb0 = 0x87; /* type */
+   out->hb1 = 0x01; /* version */
+   out->hb2 = 0x1A; /* length */
+   out->sb[0] = buf[3]; /* checksum */
+   i = 1;
+   break;
+
+   case DRM_MODE_CONNECTOR_DisplayPort:
+   case DRM_MODE_CONNECTOR_eDP:
+   out->hb0 = 0x00; /* sdp id, zero */
+   out->hb1 = 0x87; /* type */
+   out->hb2 = 0x1D; /* payload len - 1 */
+   out->hb3 = (0x13 << 2); /* sdp version */
+   out->sb[0] = 0x01; /* version */
+   out->sb[1] = 0x1A; /* length */
+   i = 2;
+   break;
+
+   default:
+   return -EINVAL;
+   }
+
+   memcpy(>sb[i], [4], 26);
+   out->valid = true;
+
+   print_hex_dump(KERN_DEBUG, "HDR SB:", DUMP_PREFIX_NONE, 16, 1, out->sb,
+  sizeof(out->sb), false);
+
+   return 0;
+}
+
+static bool
+is_hdr_metadata_different(const struct drm_connector_state *old_state,
+ const struct drm_connector_state *new_state)
+{
+   struct drm_property_blob *old_blob = old_state->hdr_output_metadata;
+   struct drm_property_blob *new_blob = new_state->hdr_output_metadata;
+
+   if (old_blob != new_blob) {
+   if (old_blob && new_blob &&
+   old_blob->length == new_blob->length)
+   return memcmp(old_blob->data, new_blob->data,
+ old_blob->length);
+
+   return true;
+   }
+
+   return false;
+}
+
+static int
+amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
+struct drm_connector_state *new_con_state)
+{
+   struct drm_atomic_state *state = new_con_state->state;
+   struct drm_connector_state *old_con_state =
+   drm_atomic_get_old_connector_state(state, conn);
+   struct drm_crtc *crtc = new_con_state->crtc;
+   struct drm_crtc_state *new_crtc_state;
+   int ret;
+
+   if (!crtc)
+   return 0;
+
+   if (is_hdr_metadata_different(old_con_state, new_con_state)) {
+   struct dc_info_packet hdr_infopacket;
+
+   ret = fill_hdr_info_packet(new_con_state, _infopacket);
+   if (ret)
+   return ret;
+
+   new_crtc_state = drm_atomic_get_crtc_state(state, crtc);
+   if (IS_ERR(new_crtc_state))
+   return PTR_ERR(new_crtc_state);
+
+   /*
+* DC considers the stream backends changed if the
+* static metadata changes. Forcing the modeset also
+* gives a simple way for userspace to switch fr

[PATCH 2/2] drm/amd/display: Only force modesets when toggling HDR

2019-05-28 Thread Nicholas Kazlauskas
[Why]
We can issue HDR static metadata as part of stream updates for
non-modesets as long as we force a modeset when entering or exiting HDR.

This avoids unnecessary blanking for simple metadata updates.

[How]
When changing scaling and abm for the stream also check if HDR has
changed and send the stream update. This will only happen in non-modeset
cases.

Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 34 +++
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index eb31acca7ed6..443b13ec268d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3978,9 +3978,16 @@ amdgpu_dm_connector_atomic_check(struct drm_connector 
*conn,
 * DC considers the stream backends changed if the
 * static metadata changes. Forcing the modeset also
 * gives a simple way for userspace to switch from
-* 8bpc to 10bpc when setting the metadata.
+* 8bpc to 10bpc when setting the metadata to enter
+* or exit HDR.
+*
+* Changing the static metadata after it's been
+* set is permissible, however. So only force a
+* modeset if we're entering or exiting HDR.
 */
-   new_crtc_state->mode_changed = true;
+   new_crtc_state->mode_changed =
+   !old_con_state->hdr_output_metadata ||
+   !new_con_state->hdr_output_metadata;
}
 
return 0;
@@ -5881,7 +5888,9 @@ static void amdgpu_dm_atomic_commit_tail(struct 
drm_atomic_state *state)
struct amdgpu_crtc *acrtc = 
to_amdgpu_crtc(dm_new_con_state->base.crtc);
struct dc_surface_update dummy_updates[MAX_SURFACES];
struct dc_stream_update stream_update;
+   struct dc_info_packet hdr_packet;
struct dc_stream_status *status = NULL;
+   bool abm_changed, hdr_changed, scaling_changed;
 
memset(_updates, 0, sizeof(dummy_updates));
memset(_update, 0, sizeof(stream_update));
@@ -5898,11 +5907,19 @@ static void amdgpu_dm_atomic_commit_tail(struct 
drm_atomic_state *state)
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
 
-   if (!is_scaling_state_different(dm_new_con_state, 
dm_old_con_state) &&
-   (dm_new_crtc_state->abm_level == 
dm_old_crtc_state->abm_level))
+   scaling_changed = is_scaling_state_different(dm_new_con_state,
+dm_old_con_state);
+
+   abm_changed = dm_new_crtc_state->abm_level !=
+ dm_old_crtc_state->abm_level;
+
+   hdr_changed =
+   is_hdr_metadata_different(old_con_state, new_con_state);
+
+   if (!scaling_changed && !abm_changed && !hdr_changed)
continue;
 
-   if (is_scaling_state_different(dm_new_con_state, 
dm_old_con_state)) {
+   if (scaling_changed) {

update_stream_scaling_settings(_new_con_state->base.crtc->mode,
dm_new_con_state, (struct 
dc_stream_state *)dm_new_crtc_state->stream);
 
@@ -5910,12 +5927,17 @@ static void amdgpu_dm_atomic_commit_tail(struct 
drm_atomic_state *state)
stream_update.dst = dm_new_crtc_state->stream->dst;
}
 
-   if (dm_new_crtc_state->abm_level != 
dm_old_crtc_state->abm_level) {
+   if (abm_changed) {
dm_new_crtc_state->stream->abm_level = 
dm_new_crtc_state->abm_level;
 
stream_update.abm_level = _new_crtc_state->abm_level;
}
 
+   if (hdr_changed) {
+   fill_hdr_info_packet(new_con_state, _packet);
+   stream_update.hdr_static_metadata = _packet;
+   }
+
status = dc_stream_get_status(dm_new_crtc_state->stream);
WARN_ON(!status);
WARN_ON(!status->plane_count);
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 1/2] drm/amd/display: Switch the custom "max bpc" property to the DRM prop

2019-05-22 Thread Nicholas Kazlauskas
[Why]
The custom "max bpc" property was added to limit color depth while the
DRM one was still being merged. It's been a few kernel versions since
then and this TODO was still sticking around.

[How]
Attach the DRM max bpc property to the connector and drop all of our
custom property management. Set the max bpc to 8 by default since
DRM defaults to the max in the range which would be 16 in this case.

No behavioral changes are intended with this patch, it should just be
a refactor.

Cc: Leo Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
Acked-by: Alex Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   |  4 ---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h  |  2 --
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 29 ---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  1 -
 4 files changed, 12 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 4e944737b708..767ee6991ef4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -631,10 +631,6 @@ int amdgpu_display_modeset_create_props(struct 
amdgpu_device *adev)
 amdgpu_dither_enum_list, sz);
 
if (amdgpu_device_has_dc_support(adev)) {
-   adev->mode_info.max_bpc_property =
-   drm_property_create_range(adev->ddev, 0, "max bpc", 8, 
16);
-   if (!adev->mode_info.max_bpc_property)
-   return -ENOMEM;
adev->mode_info.abm_level_property =
drm_property_create_range(adev->ddev, 0,
"abm level", 0, 4);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index c7940af42f76..8bda00ce8816 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -332,8 +332,6 @@ struct amdgpu_mode_info {
struct drm_property *audio_property;
/* FMT dithering */
struct drm_property *dither_property;
-   /* maximum number of bits per channel for monitor color */
-   struct drm_property *max_bpc_property;
/* Adaptive Backlight Modulation (power feature) */
struct drm_property *abm_level_property;
/* it is used to allow enablement of freesync mode */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 4a1755bce96c..b8e88209ef5d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3040,14 +3040,14 @@ static void update_stream_scaling_settings(const struct 
drm_display_mode *mode,
 static enum dc_color_depth
 convert_color_depth_from_display_info(const struct drm_connector *connector)
 {
-   struct dm_connector_state *dm_conn_state =
-   to_dm_connector_state(connector->state);
uint32_t bpc = connector->display_info.bpc;
 
-   /* TODO: Remove this when there's support for max_bpc in drm */
-   if (dm_conn_state && bpc > dm_conn_state->max_bpc)
-   /* Round down to nearest even number. */
-   bpc = dm_conn_state->max_bpc - (dm_conn_state->max_bpc & 1);
+   /* TODO: Use passed in state instead of the current state. */
+   if (connector->state) {
+   bpc = connector->state->max_bpc;
+   /* Round down to the nearest even number. */
+   bpc = bpc - (bpc & 1);
+   }
 
switch (bpc) {
case 0:
@@ -3689,9 +3689,6 @@ int amdgpu_dm_connector_atomic_set_property(struct 
drm_connector *connector,
} else if (property == adev->mode_info.underscan_property) {
dm_new_state->underscan_enable = val;
ret = 0;
-   } else if (property == adev->mode_info.max_bpc_property) {
-   dm_new_state->max_bpc = val;
-   ret = 0;
} else if (property == adev->mode_info.abm_level_property) {
dm_new_state->abm_level = val;
ret = 0;
@@ -3743,9 +3740,6 @@ int amdgpu_dm_connector_atomic_get_property(struct 
drm_connector *connector,
} else if (property == adev->mode_info.underscan_property) {
*val = dm_state->underscan_enable;
ret = 0;
-   } else if (property == adev->mode_info.max_bpc_property) {
-   *val = dm_state->max_bpc;
-   ret = 0;
} else if (property == adev->mode_info.abm_level_property) {
*val = dm_state->abm_level;
ret = 0;
@@ -3808,7 +3802,6 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector 
*connector)
state->underscan_enable = false;

[PATCH v2 2/2] drm/amd/display: Use new connector state when getting color depth

2019-05-22 Thread Nicholas Kazlauskas
[Why]
The current state on the connector is queried when getting the max bpc
rather than the new state. This means that a new max bpc value can only
currently take effect on the commit *after* it changes.

The new state should be passed in instead.

[How]
Pass down the dm_state as drm state to where we do color depth lookup.

The passed in state can still be NULL when called from
amdgpu_dm_connector_mode_valid, so make sure that we have reasonable
defaults in place. That should probably be addressed at some point.

This change now (correctly) causes a modeset to occur when changing the
max bpc for a connector.

v2: Drop extra TODO.

Cc: Leo Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
Acked-by: Alex Deucher 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 27 ++-
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index b8e88209ef5d..fd0421794e0f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3038,13 +3038,13 @@ static void update_stream_scaling_settings(const struct 
drm_display_mode *mode,
 }
 
 static enum dc_color_depth
-convert_color_depth_from_display_info(const struct drm_connector *connector)
+convert_color_depth_from_display_info(const struct drm_connector *connector,
+ const struct drm_connector_state *state)
 {
uint32_t bpc = connector->display_info.bpc;
 
-   /* TODO: Use passed in state instead of the current state. */
-   if (connector->state) {
-   bpc = connector->state->max_bpc;
+   if (state) {
+   bpc = state->max_bpc;
/* Round down to the nearest even number. */
bpc = bpc - (bpc & 1);
}
@@ -3165,11 +3165,12 @@ static void 
adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_
 
 }
 
-static void
-fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream,
-const struct drm_display_mode 
*mode_in,
-const struct drm_connector 
*connector,
-const struct dc_stream_state 
*old_stream)
+static void fill_stream_properties_from_drm_display_mode(
+   struct dc_stream_state *stream,
+   const struct drm_display_mode *mode_in,
+   const struct drm_connector *connector,
+   const struct drm_connector_state *connector_state,
+   const struct dc_stream_state *old_stream)
 {
struct dc_crtc_timing *timing_out = >timing;
const struct drm_display_info *info = >display_info;
@@ -3192,7 +3193,7 @@ fill_stream_properties_from_drm_display_mode(struct 
dc_stream_state *stream,
 
timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE;
timing_out->display_color_depth = convert_color_depth_from_display_info(
-   connector);
+   connector, connector_state);
timing_out->scan_type = SCANNING_TYPE_NODATA;
timing_out->hdmi_vic = 0;
 
@@ -3389,6 +3390,8 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
 {
struct drm_display_mode *preferred_mode = NULL;
struct drm_connector *drm_connector;
+   const struct drm_connector_state *con_state =
+   dm_state ? _state->base : NULL;
struct dc_stream_state *stream = NULL;
struct drm_display_mode mode = *drm_mode;
bool native_mode_found = false;
@@ -3461,10 +3464,10 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
*/
if (!scale || mode_refresh != preferred_refresh)
fill_stream_properties_from_drm_display_mode(stream,
-   , >base, NULL);
+   , >base, con_state, NULL);
else
fill_stream_properties_from_drm_display_mode(stream,
-   , >base, old_stream);
+   , >base, con_state, old_stream);
 
update_stream_scaling_settings(, dm_state, stream);
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 2/2] drm/amd/display: Use new connector state when getting color depth

2019-05-22 Thread Nicholas Kazlauskas
[Why]
The current state on the connector is queried when getting the max bpc
rather than the new state. This means that a new max bpc value can only
currently take effect on the commit *after* it changes.

The new state should be passed in instead.

[How]
Pass down the dm_state as drm state to where we do color depth lookup.

The passed in state can still be NULL when called from
amdgpu_dm_connector_mode_valid, so make sure that we have reasonable
defaults in place. That should probably be addressed at some point.

This change now (correctly) causes a modeset to occur when changing the
max bpc for a connector.

Cc: Leo Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 26 +++
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index a7a9e4d81a17..580c324891fd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3038,13 +3038,14 @@ static void update_stream_scaling_settings(const struct 
drm_display_mode *mode,
 }
 
 static enum dc_color_depth
-convert_color_depth_from_display_info(const struct drm_connector *connector)
+convert_color_depth_from_display_info(const struct drm_connector *connector,
+ const struct drm_connector_state *state)
 {
uint32_t bpc = 8;
 
/* TODO: Use passed in state instead of the current state. */
-   if (connector->state) {
-   bpc = connector->state->max_bpc;
+   if (state) {
+   bpc = state->max_bpc;
/* Round down to the nearest even number. */
bpc = bpc - (bpc & 1);
}
@@ -3165,11 +3166,12 @@ static void 
adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_
 
 }
 
-static void
-fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream,
-const struct drm_display_mode 
*mode_in,
-const struct drm_connector 
*connector,
-const struct dc_stream_state 
*old_stream)
+static void fill_stream_properties_from_drm_display_mode(
+   struct dc_stream_state *stream,
+   const struct drm_display_mode *mode_in,
+   const struct drm_connector *connector,
+   const struct drm_connector_state *connector_state,
+   const struct dc_stream_state *old_stream)
 {
struct dc_crtc_timing *timing_out = >timing;
const struct drm_display_info *info = >display_info;
@@ -3192,7 +3194,7 @@ fill_stream_properties_from_drm_display_mode(struct 
dc_stream_state *stream,
 
timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE;
timing_out->display_color_depth = convert_color_depth_from_display_info(
-   connector);
+   connector, connector_state);
timing_out->scan_type = SCANNING_TYPE_NODATA;
timing_out->hdmi_vic = 0;
 
@@ -3389,6 +3391,8 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
 {
struct drm_display_mode *preferred_mode = NULL;
struct drm_connector *drm_connector;
+   const struct drm_connector_state *con_state =
+   dm_state ? _state->base : NULL;
struct dc_stream_state *stream = NULL;
struct drm_display_mode mode = *drm_mode;
bool native_mode_found = false;
@@ -3461,10 +3465,10 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
*/
if (!scale || mode_refresh != preferred_refresh)
fill_stream_properties_from_drm_display_mode(stream,
-   , >base, NULL);
+   , >base, con_state, NULL);
else
fill_stream_properties_from_drm_display_mode(stream,
-   , >base, old_stream);
+   , >base, con_state, old_stream);
 
update_stream_scaling_settings(, dm_state, stream);
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 1/2] drm/amd/display: Switch the custom "max bpc" property to the DRM prop

2019-05-22 Thread Nicholas Kazlauskas
[Why]
The custom "max bpc" property was added to limit color depth while the
DRM one was still being merged. It's been a few kernel versions since
then and this TODO was still sticking around.

[How]
Attach the DRM max bpc property to the connector and drop all of our
custom property management. Set the max bpc to 8 by default since
DRM defaults to the max in the range which would be 16 in this case.

No behavioral changes are intended with this patch, it should just be
a refactor.

Cc: Leo Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   |  4 ---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h  |  2 --
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 31 ---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  1 -
 4 files changed, 13 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 4e944737b708..767ee6991ef4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -631,10 +631,6 @@ int amdgpu_display_modeset_create_props(struct 
amdgpu_device *adev)
 amdgpu_dither_enum_list, sz);
 
if (amdgpu_device_has_dc_support(adev)) {
-   adev->mode_info.max_bpc_property =
-   drm_property_create_range(adev->ddev, 0, "max bpc", 8, 
16);
-   if (!adev->mode_info.max_bpc_property)
-   return -ENOMEM;
adev->mode_info.abm_level_property =
drm_property_create_range(adev->ddev, 0,
"abm level", 0, 4);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index c7940af42f76..8bda00ce8816 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -332,8 +332,6 @@ struct amdgpu_mode_info {
struct drm_property *audio_property;
/* FMT dithering */
struct drm_property *dither_property;
-   /* maximum number of bits per channel for monitor color */
-   struct drm_property *max_bpc_property;
/* Adaptive Backlight Modulation (power feature) */
struct drm_property *abm_level_property;
/* it is used to allow enablement of freesync mode */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 4a1755bce96c..a7a9e4d81a17 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3040,14 +3040,14 @@ static void update_stream_scaling_settings(const struct 
drm_display_mode *mode,
 static enum dc_color_depth
 convert_color_depth_from_display_info(const struct drm_connector *connector)
 {
-   struct dm_connector_state *dm_conn_state =
-   to_dm_connector_state(connector->state);
-   uint32_t bpc = connector->display_info.bpc;
+   uint32_t bpc = 8;
 
-   /* TODO: Remove this when there's support for max_bpc in drm */
-   if (dm_conn_state && bpc > dm_conn_state->max_bpc)
-   /* Round down to nearest even number. */
-   bpc = dm_conn_state->max_bpc - (dm_conn_state->max_bpc & 1);
+   /* TODO: Use passed in state instead of the current state. */
+   if (connector->state) {
+   bpc = connector->state->max_bpc;
+   /* Round down to the nearest even number. */
+   bpc = bpc - (bpc & 1);
+   }
 
switch (bpc) {
case 0:
@@ -3689,9 +3689,6 @@ int amdgpu_dm_connector_atomic_set_property(struct 
drm_connector *connector,
} else if (property == adev->mode_info.underscan_property) {
dm_new_state->underscan_enable = val;
ret = 0;
-   } else if (property == adev->mode_info.max_bpc_property) {
-   dm_new_state->max_bpc = val;
-   ret = 0;
} else if (property == adev->mode_info.abm_level_property) {
dm_new_state->abm_level = val;
ret = 0;
@@ -3743,9 +3740,6 @@ int amdgpu_dm_connector_atomic_get_property(struct 
drm_connector *connector,
} else if (property == adev->mode_info.underscan_property) {
*val = dm_state->underscan_enable;
ret = 0;
-   } else if (property == adev->mode_info.max_bpc_property) {
-   *val = dm_state->max_bpc;
-   ret = 0;
} else if (property == adev->mode_info.abm_level_property) {
*val = dm_state->abm_level;
ret = 0;
@@ -3808,7 +3802,6 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector 
*connector)
state->underscan_enable = false;

[PATCH v2] drm/amd/display: Use long for signed error code checks in commit planes

2019-05-02 Thread Nicholas Kazlauskas
[Why]

The type of 'r' is uint32_t and the return codes for both:

- reservation_object_wait_timeout_rcu
- amdgpu_bo_reserve

...are signed. While it works for the latter since the check is
done on != 0 it doesn't work for the former since we check <= 0.

[How]

Make 'r' a long in commit planes so we're not doing any unsigned/signed
conversion here in the first place.

v2: use long instead of int (Christian)

Cc: Christian König 
Reported-by: Dan Carpenter 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index becd8cb3aab6..ac22f7351a42 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5332,7 +5332,7 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
struct drm_crtc *pcrtc,
bool wait_for_vblank)
 {
-   uint32_t i, r;
+   uint32_t i;
uint64_t timestamp_ns;
struct drm_plane *plane;
struct drm_plane_state *old_plane_state, *new_plane_state;
@@ -5343,6 +5343,7 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
struct dm_crtc_state *dm_old_crtc_state =
to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, 
pcrtc));
int planes_count = 0, vpos, hpos;
+   long r;
unsigned long flags;
struct amdgpu_bo *abo;
uint64_t tiling_flags;
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Use int for signed error code checks in commit planes

2019-05-02 Thread Nicholas Kazlauskas
[Why]

The type of 'r' is uint32_t and the return codes for both:

- reservation_object_wait_timeout_rcu
- amdgpu_bo_reserve

...are signed. While it works for the latter since the check is
done on != 0 it doesn't work for the former since we check <= 0.

[How]

Make 'r' an int in commit planes so we're not doing any unsigned/signed
conversion here in the first place.

Reported-by: Dan Carpenter 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index becd8cb3aab6..722f863ce4a4 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5332,7 +5332,7 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
struct drm_crtc *pcrtc,
bool wait_for_vblank)
 {
-   uint32_t i, r;
+   uint32_t i;
uint64_t timestamp_ns;
struct drm_plane *plane;
struct drm_plane_state *old_plane_state, *new_plane_state;
@@ -5342,7 +5342,7 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state);
struct dm_crtc_state *dm_old_crtc_state =
to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, 
pcrtc));
-   int planes_count = 0, vpos, hpos;
+   int r, planes_count = 0, vpos, hpos;
unsigned long flags;
struct amdgpu_bo *abo;
uint64_t tiling_flags;
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Expose DRM_FORMAT_RGB565 on overlay planes

2019-04-23 Thread Nicholas Kazlauskas
RGB565 support isn't restricted to just the primary plane in DC, so
also expose support for it on overlays.

Cc: Harry Wentland 
Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index a5cacf846e1b..0d07226ca8b7 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4283,6 +4283,7 @@ static const uint32_t overlay_formats[] = {
DRM_FORMAT_RGBA,
DRM_FORMAT_XBGR,
DRM_FORMAT_ABGR,
+   DRM_FORMAT_RGB565
 };
 
 static const u32 cursor_formats[] = {
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Remove semicolon from to_dm_plane_state definition

2019-03-25 Thread Nicholas Kazlauskas
The extra ; in the macro definition creates an empty statement
preventing any variable declarations from occuring after
any use of to_dm_plane_state(...).

Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 87ca5746f861..94b77488a0e4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -57,7 +57,7 @@ struct amdgpu_hpd;
 #define to_amdgpu_encoder(x) container_of(x, struct amdgpu_encoder, base)
 #define to_amdgpu_framebuffer(x) container_of(x, struct amdgpu_framebuffer, 
base)
 
-#define to_dm_plane_state(x)   container_of(x, struct dm_plane_state, base);
+#define to_dm_plane_state(x)   container_of(x, struct dm_plane_state, base)
 
 #define AMDGPU_MAX_HPD_PINS 6
 #define AMDGPU_MAX_CRTCS 6
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2] drm/amd/display: Add debugfs entry for amdgpu_dm_visual_confirm

2019-03-22 Thread Nicholas Kazlauskas
[Why]
DC provides a few visual confirmation debug options that can be
dynamically changed at runtime to help debug surface programming issues
but we don't have any way to access it from userspace.

[How]
Add the amdgpu_dm_visual_confirm debugfs entry.
It accepts a string containing the DC visual confirm enum value using
the debugfs attribute helpers.

The debugfs_create_file_unsafe can be used instead of
debugfs_create_file as per the documentation.

v2: Use debugfs helpers for getting and setting the value (Christian)

Cc: Leo Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 39 ++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 1a9e3d3dfa38..1d5fc5ad3bee 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -995,6 +995,35 @@ static const struct drm_info_list amdgpu_dm_debugfs_list[] 
= {
{"amdgpu_target_backlight_pwm", _backlight_read},
 };
 
+/*
+ * Sets the DC visual confirm debug option from the given string.
+ * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_visual_confirm
+ */
+static int visual_confirm_set(void *data, u64 val)
+{
+   struct amdgpu_device *adev = data;
+
+   adev->dm.dc->debug.visual_confirm = (enum visual_confirm)val;
+
+   return 0;
+}
+
+/*
+ * Reads the DC visual confirm debug option value into the given buffer.
+ * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_visual_confirm
+ */
+static int visual_confirm_get(void *data, u64 *val)
+{
+   struct amdgpu_device *adev = data;
+
+   *val = adev->dm.dc->debug.visual_confirm;
+
+   return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(visual_confirm_fops, visual_confirm_get,
+visual_confirm_set, "%llu\n");
+
 int dtn_debugfs_init(struct amdgpu_device *adev)
 {
static const struct file_operations dtn_log_fops = {
@@ -1020,5 +1049,13 @@ int dtn_debugfs_init(struct amdgpu_device *adev)
adev,
_log_fops);
 
-   return PTR_ERR_OR_ZERO(ent);
+   if (IS_ERR(ent))
+   return PTR_ERR(ent);
+
+   ent = debugfs_create_file_unsafe("amdgpu_dm_visual_confirm", 0644, root,
+adev, _confirm_fops);
+   if (IS_ERR(ent))
+   return PTR_ERR(ent);
+
+   return 0;
 }
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2] drm/amd/display: Initialize stream_update with memset

2019-03-22 Thread Nicholas Kazlauskas
The brace initialization used here generates warnings on some
compilers. For example, on GCC 4.9:

[...] In function ‘dm_determine_update_type_for_commit’:
[...] error: missing braces around initializer [-Werror=missing-braces]
   struct dc_stream_update stream_update = { 0 };
  ^

Use memset to make this more portable.

v2: Specify the compiler / diagnostic in the commit message (Paul)

Cc: Sun peng Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 5b7a85e28fab..9cdd52edfc3d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5982,7 +5982,9 @@ dm_determine_update_type_for_commit(struct dc *dc,
}
 
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
new_crtc_state, i) {
-   struct dc_stream_update stream_update = { 0 };
+   struct dc_stream_update stream_update;
+
+   memset(_update, 0, sizeof(stream_update));
 
new_dm_crtc_state = to_dm_crtc_state(new_crtc_state);
old_dm_crtc_state = to_dm_crtc_state(old_crtc_state);
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Initialize stream_update with memset

2019-03-22 Thread Nicholas Kazlauskas
The brace initialization used here generates errors on some
compilers. Use memset to make this more portable.

Cc: Sun peng Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 5b7a85e28fab..9cdd52edfc3d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5982,7 +5982,9 @@ dm_determine_update_type_for_commit(struct dc *dc,
}
 
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
new_crtc_state, i) {
-   struct dc_stream_update stream_update = { 0 };
+   struct dc_stream_update stream_update;
+
+   memset(_update, 0, sizeof(stream_update));
 
new_dm_crtc_state = to_dm_crtc_state(new_crtc_state);
old_dm_crtc_state = to_dm_crtc_state(old_crtc_state);
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Only allow VRR when vrefresh is within supported range

2019-03-21 Thread Nicholas Kazlauskas
[Why]
Black screens or artifacting can occur when enabling FreeSync outside
of the supported range of the monitor. This can happen since the
supported range isn't always the min/max vrefresh range available for
the monitor.

[How]
There was previously a fix that prevented this from happening in the
low range but it didn't cover the upper range. Expand the condition
to include both.

Cc: Sun peng Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 01a46119512b..5b7a85e28fab 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5551,9 +5551,11 @@ static void get_freesync_config_for_crtc(
struct amdgpu_dm_connector *aconnector =
to_amdgpu_dm_connector(new_con_state->base.connector);
struct drm_display_mode *mode = _crtc_state->base.mode;
+   int vrefresh = drm_mode_vrefresh(mode);
 
new_crtc_state->vrr_supported = new_con_state->freesync_capable &&
-   aconnector->min_vfreq <= drm_mode_vrefresh(mode);
+   vrefresh >= aconnector->min_vfreq &&
+   vrefresh <= aconnector->max_vfreq;
 
if (new_crtc_state->vrr_supported) {
new_crtc_state->stream->ignore_msa_timing_param = true;
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Add debugfs entry for amdgpu_dm_visual_confirm

2019-03-15 Thread Nicholas Kazlauskas
[Why]
DC provides a few visual confirmation debug options that can be
dynamically changed at runtime to help debug surface programming issues
but we don't have any way to access it from userspace.

[How]
Add the amdgpu_dm_visual_confirm debugfs entry.
It accepts a string containing the DC visual confirm enum value.

Cc: Leo Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 77 ++-
 1 file changed, 75 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 4a55cde027cf..1d6bfb84d7cf 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -803,6 +803,65 @@ static ssize_t dtn_log_write(
return size;
 }
 
+/*
+ * Reads the DC visual confirm debug option value into the given buffer.
+ * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_visual_confirm
+ */
+static ssize_t visual_confirm_read(struct file *f, char __user *buf,
+  size_t size, loff_t *pos)
+{
+   struct amdgpu_device *adev = file_inode(f)->i_private;
+   struct dc *dc = adev->dm.dc;
+   size_t to_copy = 0;
+   int len;
+   char tmp[16];
+
+   if (!buf || !size)
+   return -EINVAL;
+
+   len = snprintf(tmp, sizeof(tmp), "%d\n", dc->debug.visual_confirm);
+   if (len < 0 || len >= sizeof(tmp))
+   return -EINVAL;
+
+   if (*pos >= len)
+   return 0;
+
+   to_copy = len - *pos;
+   if (to_copy > size)
+   return 0;
+
+   if (copy_to_user(buf, tmp + *pos, to_copy))
+   return -EFAULT;
+
+   *pos += to_copy;
+
+   return to_copy;
+}
+
+/*
+ * Sets the DC visual confirm debug option from the given string.
+ * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_visual_confirm
+ */
+static ssize_t visual_confirm_write(struct file *f, const char __user *buf,
+   size_t size, loff_t *pos)
+{
+   struct amdgpu_device *adev = file_inode(f)->i_private;
+   struct dc *dc = adev->dm.dc;
+   int ret;
+   u16 val;
+
+   if (size == 0)
+   return 0;
+
+   ret = kstrtou16_from_user(buf, size, 0, );
+   if (ret)
+   return ret;
+
+   dc->debug.visual_confirm = val;
+
+   return size;
+}
+
 /*
  * Backlight at this moment.  Read only.
  * As written to display, taking ABM and backlight lut into account.
@@ -850,7 +909,12 @@ int dtn_debugfs_init(struct amdgpu_device *adev)
.write = dtn_log_write,
.llseek = default_llseek
};
-
+   static const struct file_operations visual_confirm_fops = {
+   .owner = THIS_MODULE,
+   .read = visual_confirm_read,
+   .write = visual_confirm_write,
+   .llseek = default_llseek
+   };
struct drm_minor *minor = adev->ddev->primary;
struct dentry *ent, *root = minor->debugfs_root;
int ret;
@@ -867,5 +931,14 @@ int dtn_debugfs_init(struct amdgpu_device *adev)
adev,
_log_fops);
 
-   return PTR_ERR_OR_ZERO(ent);
+   if (IS_ERR(ent))
+   return PTR_ERR(ent);
+
+   ent = debugfs_create_file("amdgpu_dm_visual_confirm", 0644, root, adev,
+ _confirm_fops);
+
+   if (IS_ERR(ent))
+   return PTR_ERR(ent);
+
+   return 0;
 }
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Only put primary planes into the mode_info->planes list

2019-03-14 Thread Nicholas Kazlauskas
We want DRM planes to be initialized in the following order:

- primary planes
- overlay planes
- cursor planes

to support existing userspace expectations for plane z-ordering. This
means that we also need to register CRTCs after all planes have been
initialized since overlay planes can be placed on any CRTC.

So the only reason why we have the mode_info->planes list is to
remember the primary planes for use later when we need to register
the CRTC.

Overlay planes have no purpose being in this list. DRM will cleanup
any planes that we've registered for us, so the only planes that need to
be explicitly cleaned up are the ones that have failed to register.

By dropping the explicit free on every plane in the mode_info->planes
list this patch also fixes a double-free in the case where we fail to
initialize only some of the planes.

Cc: Leo Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 19 +--
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index cde0da3ae964..f770de36121f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1818,8 +1818,6 @@ static int initialize_plane(struct amdgpu_display_manager 
*dm,
int ret = 0;
 
plane = kzalloc(sizeof(struct drm_plane), GFP_KERNEL);
-   mode_info->planes[plane_id] = plane;
-
if (!plane) {
DRM_ERROR("KMS: Failed to allocate plane\n");
return -ENOMEM;
@@ -1836,13 +1834,17 @@ static int initialize_plane(struct 
amdgpu_display_manager *dm,
if (plane_id >= dm->dc->caps.max_streams)
possible_crtcs = 0xff;
 
-   ret = amdgpu_dm_plane_init(dm, mode_info->planes[plane_id], 
possible_crtcs);
+   ret = amdgpu_dm_plane_init(dm, plane, possible_crtcs);
 
if (ret) {
DRM_ERROR("KMS: Failed to initialize plane\n");
+   kfree(plane);
return ret;
}
 
+   if (mode_info)
+   mode_info->planes[plane_id] = plane;
+
return ret;
 }
 
@@ -1885,7 +1887,7 @@ static int amdgpu_dm_initialize_drm_device(struct 
amdgpu_device *adev)
struct amdgpu_encoder *aencoder = NULL;
struct amdgpu_mode_info *mode_info = >mode_info;
uint32_t link_cnt;
-   int32_t overlay_planes, primary_planes, total_planes;
+   int32_t overlay_planes, primary_planes;
enum dc_connection_type new_connection_type = dc_connection_none;
 
link_cnt = dm->dc->caps.max_links;
@@ -1914,9 +1916,7 @@ static int amdgpu_dm_initialize_drm_device(struct 
amdgpu_device *adev)
 
/* There is one primary plane per CRTC */
primary_planes = dm->dc->caps.max_streams;
-
-   total_planes = primary_planes + overlay_planes;
-   ASSERT(total_planes <= AMDGPU_MAX_PLANES);
+   ASSERT(primary_planes <= AMDGPU_MAX_PLANES);
 
/*
 * Initialize primary planes, implicit planes for legacy IOCTLS.
@@ -1937,7 +1937,7 @@ static int amdgpu_dm_initialize_drm_device(struct 
amdgpu_device *adev)
 * Order is reversed to match iteration order in atomic check.
 */
for (i = (overlay_planes - 1); i >= 0; i--) {
-   if (initialize_plane(dm, mode_info, primary_planes + i,
+   if (initialize_plane(dm, NULL, primary_planes + i,
 DRM_PLANE_TYPE_OVERLAY)) {
DRM_ERROR("KMS: Failed to initialize overlay plane\n");
goto fail;
@@ -2041,8 +2041,7 @@ static int amdgpu_dm_initialize_drm_device(struct 
amdgpu_device *adev)
 fail:
kfree(aencoder);
kfree(aconnector);
-   for (i = 0; i < primary_planes; i++)
-   kfree(mode_info->planes[i]);
+
return -EINVAL;
 }
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Respect DRM framebuffer info for video surfaces

2019-03-13 Thread Nicholas Kazlauskas
[Why]
Incorrect hardcoded assumptions are made regarding luma and chroma
alignment. The actual values set for the DRM framebuffer should be used
when programming the address.

[How]
Respect the given pitch for both luma and chroma planes - it's not like
we can force the alignment to anything else at this point anyway.

Use the FB offset for the chroma planes directly. DRM already
provides this to us so there's no need to calculate it manually.

While we don't actually use the chroma surface size parameters on Raven,
these should have technically been fb->width / 2 and fb->height / 2
since the chroma plane is half size of the luma plane for NV12.

Leave a TODO indicating that those should be set based on the actual
surface format instead since this is only correct for YUV420 formats.

Cc: Leo Li 
Cc: Harry Wentland 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 21 +--
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index cde0da3ae964..5f1e23ba75e1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2465,8 +2465,7 @@ fill_plane_tiling_attributes(struct amdgpu_device *adev,
address->grph.addr.high_part = upper_32_bits(afb->address);
} else {
const struct drm_framebuffer *fb = >base;
-   uint64_t awidth = ALIGN(fb->width, 64);
-   uint64_t chroma_addr = afb->address + awidth * fb->height;
+   uint64_t chroma_addr = afb->address + fb->offsets[1];
 
address->type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
address->video_progressive.luma_addr.low_part =
@@ -2542,7 +2541,6 @@ static int fill_plane_attributes_from_fb(struct 
amdgpu_device *adev,
 const struct amdgpu_framebuffer 
*amdgpu_fb)
 {
uint64_t tiling_flags;
-   unsigned int awidth;
const struct drm_framebuffer *fb = _fb->base;
int ret = 0;
struct drm_format_name_buf format_name;
@@ -2602,20 +2600,21 @@ static int fill_plane_attributes_from_fb(struct 
amdgpu_device *adev,
plane_state->color_space = COLOR_SPACE_SRGB;
 
} else {
-   awidth = ALIGN(fb->width, 64);
-
plane_state->plane_size.video.luma_size.x = 0;
plane_state->plane_size.video.luma_size.y = 0;
-   plane_state->plane_size.video.luma_size.width = awidth;
+   plane_state->plane_size.video.luma_size.width = fb->width;
plane_state->plane_size.video.luma_size.height = fb->height;
-   /* TODO: unhardcode */
-   plane_state->plane_size.video.luma_pitch = awidth;
+   plane_state->plane_size.video.luma_pitch =
+   fb->pitches[0] / fb->format->cpp[0];
 
plane_state->plane_size.video.chroma_size.x = 0;
plane_state->plane_size.video.chroma_size.y = 0;
-   plane_state->plane_size.video.chroma_size.width = awidth;
-   plane_state->plane_size.video.chroma_size.height = fb->height;
-   plane_state->plane_size.video.chroma_pitch = awidth / 2;
+   /* TODO: set these based on surface format */
+   plane_state->plane_size.video.chroma_size.width = fb->width / 2;
+   plane_state->plane_size.video.chroma_size.height = fb->height / 
2;
+
+   plane_state->plane_size.video.chroma_pitch =
+   fb->pitches[1] / fb->format->cpp[1];
 
/* TODO: unhardcode */
plane_state->color_space = COLOR_SPACE_YCBCR709;
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amdgpu: Only clear dumb buffers if ring is enabled

2019-03-11 Thread Nicholas Kazlauskas
The buffers should be cleared when possible but we also don't want
buffer creation to fail in the rare case where the ring isn't ready
during the call. This could happen during some suspend/resume sequences.

Cc: Christian König 
Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index a58072bbc9b8..9ee8d7a3c6d4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -733,18 +733,25 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
struct amdgpu_device *adev = dev->dev_private;
struct drm_gem_object *gobj;
uint32_t handle;
+   u64 flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
u32 domain;
int r;
 
+   /*
+* The buffer returned from this function should be cleared, but
+* it can only be done if the ring is enabled or we'll fail to
+* create the buffer.
+*/
+   if (adev->mman.buffer_funcs_enabled)
+   flags |= AMDGPU_GEM_CREATE_VRAM_CLEARED;
+
args->pitch = amdgpu_align_pitch(adev, args->width,
 DIV_ROUND_UP(args->bpp, 8), 0);
args->size = (u64)args->pitch * args->height;
args->size = ALIGN(args->size, PAGE_SIZE);
domain = amdgpu_bo_get_preferred_pin_domain(adev,
amdgpu_display_supported_domains(adev));
-   r = amdgpu_gem_object_create(adev, args->size, 0, domain,
-AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
-AMDGPU_GEM_CREATE_VRAM_CLEARED,
+   r = amdgpu_gem_object_create(adev, args->size, 0, domain, flags,
 ttm_bo_type_device, NULL, );
if (r)
return -ENOMEM;
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Fix plane address updates for video surface formats

2019-03-11 Thread Nicholas Kazlauskas
[Why]
For new DC planes the correct plane address fields are filled based
on whether the plane had a graphics or video format.

However, when we perform stream and plane updates using DC we only ever
fill in the graphics format fields. This causing corruption and hangs
when using video surface formats like NV12 for planes.

[How]
Use the same logic everywhere we update dc_plane_address - always
fill in the correct fields based on the surface format type.

There are 3 places this is done:

- Atomic check, during DC plane creation
- Atomic commit, during plane prepare_fb
- Atomic commit tail, during amdgpu_dm_commit_planes

We use the fill_plane_tiling_attributes in all 3 locations and it
already needs the address to update DCC attributes, so the surface
address update logic can be moved into this helper.

Cc: Leo Li 
Signed-off-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 57 +--
 1 file changed, 26 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 59a8045c9e2a..e0c0621f40d4 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2457,6 +2457,27 @@ fill_plane_tiling_attributes(struct amdgpu_device *adev,
 
memset(tiling_info, 0, sizeof(*tiling_info));
memset(dcc, 0, sizeof(*dcc));
+   memset(address, 0, sizeof(*address));
+
+   if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
+   address->type = PLN_ADDR_TYPE_GRAPHICS;
+   address->grph.addr.low_part = lower_32_bits(afb->address);
+   address->grph.addr.high_part = upper_32_bits(afb->address);
+   } else {
+   const struct drm_framebuffer *fb = >base;
+   uint64_t awidth = ALIGN(fb->width, 64);
+   uint64_t chroma_addr = afb->address + awidth * fb->height;
+
+   address->type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
+   address->video_progressive.luma_addr.low_part =
+   lower_32_bits(afb->address);
+   address->video_progressive.luma_addr.high_part =
+   upper_32_bits(afb->address);
+   address->video_progressive.chroma_addr.low_part =
+   lower_32_bits(chroma_addr);
+   address->video_progressive.chroma_addr.high_part =
+   upper_32_bits(chroma_addr);
+   }
 
/* Fill GFX8 params */
if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == 
DC_ARRAY_2D_TILED_THIN1) {
@@ -2571,7 +2592,6 @@ static int fill_plane_attributes_from_fb(struct 
amdgpu_device *adev,
memset(_state->address, 0, sizeof(plane_state->address));
 
if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
-   plane_state->address.type = PLN_ADDR_TYPE_GRAPHICS;
plane_state->plane_size.grph.surface_size.x = 0;
plane_state->plane_size.grph.surface_size.y = 0;
plane_state->plane_size.grph.surface_size.width = fb->width;
@@ -2583,7 +2603,7 @@ static int fill_plane_attributes_from_fb(struct 
amdgpu_device *adev,
 
} else {
awidth = ALIGN(fb->width, 64);
-   plane_state->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
+
plane_state->plane_size.video.luma_size.x = 0;
plane_state->plane_size.video.luma_size.y = 0;
plane_state->plane_size.video.luma_size.width = awidth;
@@ -3738,10 +3758,8 @@ static int dm_plane_helper_prepare_fb(struct drm_plane 
*plane,
struct drm_gem_object *obj;
struct amdgpu_device *adev;
struct amdgpu_bo *rbo;
-   uint64_t chroma_addr = 0;
struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old;
-   uint64_t tiling_flags, dcc_address;
-   unsigned int awidth;
+   uint64_t tiling_flags;
uint32_t domain;
int r;
 
@@ -3794,29 +3812,9 @@ static int dm_plane_helper_prepare_fb(struct drm_plane 
*plane,
dm_plane_state_old->dc_state != 
dm_plane_state_new->dc_state) {
struct dc_plane_state *plane_state = 
dm_plane_state_new->dc_state;
 
-   if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
-   plane_state->address.grph.addr.low_part = 
lower_32_bits(afb->address);
-   plane_state->address.grph.addr.high_part = 
upper_32_bits(afb->address);
-
-   dcc_address =
-   get_dcc_address(afb->address, tiling_flags);
-   plane_state->address.grph.meta_addr.low_part =
-   lower_32_bits(dcc_address);
-   plane_state->address.grph.meta_addr.hig

[PATCH] drm/amdgpu: Clear VRAM for DRM dumb_create buffers

2019-03-08 Thread Nicholas Kazlauskas
The dumb_create API isn't intended for high performance rendering
and it's more useful for userspace (ie. IGT) to have them precleared.

The bonus here is that we also won't needlessly leak whatever was
previously in VRAM, but it also probably wasn't sensitive if it was
going through this API.

Signed-off-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index fcaaac30e84b..a58072bbc9b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -743,7 +743,8 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
domain = amdgpu_bo_get_preferred_pin_domain(adev,
amdgpu_display_supported_domains(adev));
r = amdgpu_gem_object_create(adev, args->size, 0, domain,
-AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+AMDGPU_GEM_CREATE_VRAM_CLEARED,
 ttm_bo_type_device, NULL, );
if (r)
return -ENOMEM;
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

  1   2   >