mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-27 16:55:13 +07:00
drm/amd/display: Add MST atomic routines
- Adding encoder atomic check to find vcpi slots for a connector - Using DRM helper functions to calculate PBN - Adding connector atomic check to release vcpi slots if connector loses CRTC - Calculate PBN and VCPI slots only once during atomic check and store them on crtc_state to eliminate redundant calculation - Call drm_dp_mst_atomic_check to verify validity of MST topology during state atomic check v2: squashed previous 3 separate patches, removed DSC PBN calculation, and added PBN and VCPI slots properties to amdgpu connector v3: - moved vcpi_slots and pbn properties to dm_crtc_state and dc_stream_state - updates stream's vcpi_slots and pbn on commit - separated patch from the DSC MST series v4: - set vcpi_slots and pbn properties to dm_connector_state - copy porperties from connector state on to crtc state v5: - keep the pbn and vcpi values only on connnector state - added a void pointer to the stream state instead on two ints, because dc_stream_state is OS agnostic. Pointer points to the current dm_connector_state. v6: - Remove new param from stream v7: - Fix error with using max capable bpc v8: - squash in fix from Gustavo A. R. Silva Reviewed-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
622b2a0ab6
commit
3261e013c0
@ -4095,7 +4095,8 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector)
|
|||||||
state->underscan_hborder = 0;
|
state->underscan_hborder = 0;
|
||||||
state->underscan_vborder = 0;
|
state->underscan_vborder = 0;
|
||||||
state->base.max_requested_bpc = 8;
|
state->base.max_requested_bpc = 8;
|
||||||
|
state->vcpi_slots = 0;
|
||||||
|
state->pbn = 0;
|
||||||
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
|
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
|
||||||
state->abm_level = amdgpu_dm_abm_level;
|
state->abm_level = amdgpu_dm_abm_level;
|
||||||
|
|
||||||
@ -4123,7 +4124,8 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector)
|
|||||||
new_state->underscan_enable = state->underscan_enable;
|
new_state->underscan_enable = state->underscan_enable;
|
||||||
new_state->underscan_hborder = state->underscan_hborder;
|
new_state->underscan_hborder = state->underscan_hborder;
|
||||||
new_state->underscan_vborder = state->underscan_vborder;
|
new_state->underscan_vborder = state->underscan_vborder;
|
||||||
|
new_state->vcpi_slots = state->vcpi_slots;
|
||||||
|
new_state->pbn = state->pbn;
|
||||||
return &new_state->base;
|
return &new_state->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4520,10 +4522,64 @@ static void dm_encoder_helper_disable(struct drm_encoder *encoder)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int convert_dc_color_depth_into_bpc (enum dc_color_depth display_color_depth)
|
||||||
|
{
|
||||||
|
switch (display_color_depth) {
|
||||||
|
case COLOR_DEPTH_666:
|
||||||
|
return 6;
|
||||||
|
case COLOR_DEPTH_888:
|
||||||
|
return 8;
|
||||||
|
case COLOR_DEPTH_101010:
|
||||||
|
return 10;
|
||||||
|
case COLOR_DEPTH_121212:
|
||||||
|
return 12;
|
||||||
|
case COLOR_DEPTH_141414:
|
||||||
|
return 14;
|
||||||
|
case COLOR_DEPTH_161616:
|
||||||
|
return 16;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
|
static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
|
||||||
struct drm_crtc_state *crtc_state,
|
struct drm_crtc_state *crtc_state,
|
||||||
struct drm_connector_state *conn_state)
|
struct drm_connector_state *conn_state)
|
||||||
{
|
{
|
||||||
|
struct drm_atomic_state *state = crtc_state->state;
|
||||||
|
struct drm_connector *connector = conn_state->connector;
|
||||||
|
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
|
||||||
|
struct dm_connector_state *dm_new_connector_state = to_dm_connector_state(conn_state);
|
||||||
|
const struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
|
||||||
|
struct drm_dp_mst_topology_mgr *mst_mgr;
|
||||||
|
struct drm_dp_mst_port *mst_port;
|
||||||
|
enum dc_color_depth color_depth;
|
||||||
|
int clock, bpp = 0;
|
||||||
|
|
||||||
|
if (!aconnector->port || !aconnector->dc_sink)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mst_port = aconnector->port;
|
||||||
|
mst_mgr = &aconnector->mst_port->mst_mgr;
|
||||||
|
|
||||||
|
if (!crtc_state->connectors_changed && !crtc_state->mode_changed)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!state->duplicated) {
|
||||||
|
color_depth = convert_color_depth_from_display_info(connector, conn_state);
|
||||||
|
bpp = convert_dc_color_depth_into_bpc(color_depth) * 3;
|
||||||
|
clock = adjusted_mode->clock;
|
||||||
|
dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp);
|
||||||
|
}
|
||||||
|
dm_new_connector_state->vcpi_slots = drm_dp_atomic_find_vcpi_slots(state,
|
||||||
|
mst_mgr,
|
||||||
|
mst_port,
|
||||||
|
dm_new_connector_state->pbn);
|
||||||
|
if (dm_new_connector_state->vcpi_slots < 0) {
|
||||||
|
DRM_DEBUG_ATOMIC("failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots);
|
||||||
|
return dm_new_connector_state->vcpi_slots;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7566,6 +7622,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
/* Perform validation of MST topology in the state*/
|
||||||
|
ret = drm_dp_mst_atomic_check(state);
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
if (state->legacy_cursor_update) {
|
if (state->legacy_cursor_update) {
|
||||||
/*
|
/*
|
||||||
* This is a fast cursor update coming from the plane update
|
* This is a fast cursor update coming from the plane update
|
||||||
|
@ -359,6 +359,8 @@ struct dm_connector_state {
|
|||||||
bool underscan_enable;
|
bool underscan_enable;
|
||||||
bool freesync_capable;
|
bool freesync_capable;
|
||||||
uint8_t abm_level;
|
uint8_t abm_level;
|
||||||
|
int vcpi_slots;
|
||||||
|
uint64_t pbn;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define to_dm_connector_state(x)\
|
#define to_dm_connector_state(x)\
|
||||||
|
@ -182,15 +182,19 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
|
|||||||
bool enable)
|
bool enable)
|
||||||
{
|
{
|
||||||
struct amdgpu_dm_connector *aconnector;
|
struct amdgpu_dm_connector *aconnector;
|
||||||
|
struct dm_connector_state *dm_conn_state;
|
||||||
struct drm_dp_mst_topology_mgr *mst_mgr;
|
struct drm_dp_mst_topology_mgr *mst_mgr;
|
||||||
struct drm_dp_mst_port *mst_port;
|
struct drm_dp_mst_port *mst_port;
|
||||||
int slots = 0;
|
|
||||||
bool ret;
|
bool ret;
|
||||||
int clock;
|
|
||||||
int bpp = 0;
|
|
||||||
int pbn = 0;
|
|
||||||
|
|
||||||
aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
|
aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
|
||||||
|
/* Accessing the connector state is required for vcpi_slots allocation
|
||||||
|
* and directly relies on behaviour in commit check
|
||||||
|
* that blocks before commit guaranteeing that the state
|
||||||
|
* is not gonna be swapped while still in use in commit tail */
|
||||||
|
|
||||||
|
dm_conn_state = to_dm_connector_state(aconnector->base.state);
|
||||||
|
|
||||||
|
|
||||||
if (!aconnector || !aconnector->mst_port)
|
if (!aconnector || !aconnector->mst_port)
|
||||||
return false;
|
return false;
|
||||||
@ -203,42 +207,10 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
|
|||||||
mst_port = aconnector->port;
|
mst_port = aconnector->port;
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
clock = stream->timing.pix_clk_100hz / 10;
|
|
||||||
|
|
||||||
switch (stream->timing.display_color_depth) {
|
|
||||||
|
|
||||||
case COLOR_DEPTH_666:
|
|
||||||
bpp = 6;
|
|
||||||
break;
|
|
||||||
case COLOR_DEPTH_888:
|
|
||||||
bpp = 8;
|
|
||||||
break;
|
|
||||||
case COLOR_DEPTH_101010:
|
|
||||||
bpp = 10;
|
|
||||||
break;
|
|
||||||
case COLOR_DEPTH_121212:
|
|
||||||
bpp = 12;
|
|
||||||
break;
|
|
||||||
case COLOR_DEPTH_141414:
|
|
||||||
bpp = 14;
|
|
||||||
break;
|
|
||||||
case COLOR_DEPTH_161616:
|
|
||||||
bpp = 16;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ASSERT(bpp != 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bpp = bpp * 3;
|
|
||||||
|
|
||||||
/* TODO need to know link rate */
|
|
||||||
|
|
||||||
pbn = drm_dp_calc_pbn_mode(clock, bpp);
|
|
||||||
|
|
||||||
slots = drm_dp_find_vcpi_slots(mst_mgr, pbn);
|
|
||||||
ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots);
|
|
||||||
|
|
||||||
|
ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port,
|
||||||
|
dm_conn_state->pbn,
|
||||||
|
dm_conn_state->vcpi_slots);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -246,11 +246,43 @@ dm_dp_mst_detect(struct drm_connector *connector,
|
|||||||
aconnector->port);
|
aconnector->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dm_dp_mst_atomic_check(struct drm_connector *connector,
|
||||||
|
struct drm_atomic_state *state)
|
||||||
|
{
|
||||||
|
struct drm_connector_state *new_conn_state =
|
||||||
|
drm_atomic_get_new_connector_state(state, connector);
|
||||||
|
struct drm_connector_state *old_conn_state =
|
||||||
|
drm_atomic_get_old_connector_state(state, connector);
|
||||||
|
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
|
||||||
|
struct drm_crtc_state *new_crtc_state;
|
||||||
|
struct drm_dp_mst_topology_mgr *mst_mgr;
|
||||||
|
struct drm_dp_mst_port *mst_port;
|
||||||
|
|
||||||
|
mst_port = aconnector->port;
|
||||||
|
mst_mgr = &aconnector->mst_port->mst_mgr;
|
||||||
|
|
||||||
|
if (!old_conn_state->crtc)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (new_conn_state->crtc) {
|
||||||
|
new_crtc_state = drm_atomic_get_old_crtc_state(state, new_conn_state->crtc);
|
||||||
|
if (!new_crtc_state ||
|
||||||
|
!drm_atomic_crtc_needs_modeset(new_crtc_state) ||
|
||||||
|
new_crtc_state->enable)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return drm_dp_atomic_release_vcpi_slots(state,
|
||||||
|
mst_mgr,
|
||||||
|
mst_port);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = {
|
static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = {
|
||||||
.get_modes = dm_dp_mst_get_modes,
|
.get_modes = dm_dp_mst_get_modes,
|
||||||
.mode_valid = amdgpu_dm_connector_mode_valid,
|
.mode_valid = amdgpu_dm_connector_mode_valid,
|
||||||
.atomic_best_encoder = dm_mst_atomic_best_encoder,
|
.atomic_best_encoder = dm_mst_atomic_best_encoder,
|
||||||
.detect_ctx = dm_dp_mst_detect,
|
.detect_ctx = dm_dp_mst_detect,
|
||||||
|
.atomic_check = dm_dp_mst_atomic_check,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder)
|
static void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder)
|
||||||
|
Loading…
Reference in New Issue
Block a user