mirror of
https://github.com/torvalds/linux.git
synced 2026-04-25 18:12:26 -04:00
Merge tag 'drm-next-5.4-2019-08-23' of git://people.freedesktop.org/~agd5f/linux into drm-next
drm-next-5.4-2019-08-23: amdgpu: - Enable power features on Navi12 - Enable power features on Arcturus - RAS updates - Initial Renoir APU support - Enable power featyres on Renoir - DC gamma fixes - DCN2 fixes - GPU reset support for Picasso - Misc cleanups and fixes scheduler: - Possible race fix Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexdeucher@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190823202620.3870-1-alexander.deucher@amd.com
This commit is contained in:
@@ -694,6 +694,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
if (amdgpu_dc_feature_mask & DC_FBC_MASK)
|
||||
init_data.flags.fbc_support = true;
|
||||
|
||||
if (amdgpu_dc_feature_mask & DC_MULTI_MON_PP_MCLK_SWITCH_MASK)
|
||||
init_data.flags.multi_mon_pp_mclk_switch = true;
|
||||
|
||||
init_data.flags.power_down_display_on_boot = true;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
|
||||
@@ -3006,6 +3009,8 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
|
||||
plane_info->visible = true;
|
||||
plane_info->stereo_format = PLANE_STEREO_FORMAT_NONE;
|
||||
|
||||
plane_info->layer_index = 0;
|
||||
|
||||
ret = fill_plane_color_attributes(plane_state, plane_info->format,
|
||||
&plane_info->color_space);
|
||||
if (ret)
|
||||
@@ -3071,6 +3076,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
|
||||
dc_plane_state->global_alpha = plane_info.global_alpha;
|
||||
dc_plane_state->global_alpha_value = plane_info.global_alpha_value;
|
||||
dc_plane_state->dcc = plane_info.dcc;
|
||||
dc_plane_state->layer_index = plane_info.layer_index; // Always returns 0
|
||||
|
||||
/*
|
||||
* Always set input transfer function, since plane state is refreshed
|
||||
@@ -3142,13 +3148,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);
|
||||
}
|
||||
@@ -3502,6 +3520,10 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
|
||||
bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false;
|
||||
int mode_refresh;
|
||||
int preferred_refresh = 0;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
struct dsc_dec_dpcd_caps dsc_caps;
|
||||
uint32_t link_bandwidth_kbps;
|
||||
#endif
|
||||
|
||||
struct dc_sink *sink = NULL;
|
||||
if (aconnector == NULL) {
|
||||
@@ -3574,17 +3596,23 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
|
||||
&mode, &aconnector->base, con_state, old_stream);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
/* stream->timing.flags.DSC = 0; */
|
||||
/* */
|
||||
/* if (aconnector->dc_link && */
|
||||
/* aconnector->dc_link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT #<{(|&& */
|
||||
/* aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.is_dsc_supported|)}>#) */
|
||||
/* if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc, */
|
||||
/* &aconnector->dc_link->dpcd_caps.dsc_caps, */
|
||||
/* dc_link_bandwidth_kbps(aconnector->dc_link, dc_link_get_link_cap(aconnector->dc_link)), */
|
||||
/* &stream->timing, */
|
||||
/* &stream->timing.dsc_cfg)) */
|
||||
/* stream->timing.flags.DSC = 1; */
|
||||
stream->timing.flags.DSC = 0;
|
||||
|
||||
if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) {
|
||||
dc_dsc_parse_dsc_dpcd(aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
|
||||
aconnector->dc_link->dpcd_caps.dsc_caps.dsc_ext_caps.raw,
|
||||
&dsc_caps);
|
||||
link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link,
|
||||
dc_link_get_link_cap(aconnector->dc_link));
|
||||
|
||||
if (dsc_caps.is_dsc_supported)
|
||||
if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc,
|
||||
&dsc_caps,
|
||||
link_bandwidth_kbps,
|
||||
&stream->timing,
|
||||
&stream->timing.dsc_cfg))
|
||||
stream->timing.flags.DSC = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
update_stream_scaling_settings(&mode, dm_state, stream);
|
||||
@@ -6003,11 +6031,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
|
||||
}
|
||||
@@ -6058,23 +6084,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
|
||||
|
||||
@@ -97,17 +97,52 @@ 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 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 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(&adev->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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure dithering */
|
||||
if (!dm_need_crc_dither(source))
|
||||
dc_stream_set_dither_option(stream_state, DITHER_OPTION_TRUN8);
|
||||
else
|
||||
dc_stream_set_dither_option(stream_state,
|
||||
DITHER_OPTION_DEFAULT);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&adev->dm.dc_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
|
||||
{
|
||||
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;
|
||||
|
||||
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",
|
||||
@@ -115,14 +150,34 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!stream_state) {
|
||||
DRM_ERROR("No stream state for CRTC%d\n", crtc->index);
|
||||
return -EINVAL;
|
||||
ret = drm_modeset_lock(&crtc->mutex, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock(&crtc->commit_lock);
|
||||
commit = list_first_entry_or_null(&crtc->commit_list,
|
||||
struct drm_crtc_commit, commit_entry);
|
||||
if (commit)
|
||||
drm_crtc_commit_get(commit);
|
||||
spin_unlock(&crtc->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(
|
||||
&commit->hw_done, 10 * HZ);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
enable = amdgpu_dm_is_valid_crc_source(source);
|
||||
crtc_state = to_dm_crtc_state(crtc->state);
|
||||
|
||||
mutex_lock(&adev->dm.dc_lock);
|
||||
/*
|
||||
* USER REQ SRC | CURRENT SRC | BEHAVIOR
|
||||
* -----------------------------
|
||||
@@ -137,38 +192,41 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
|
||||
* DPRX DITHER | XXXX | 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, &conn_iter);
|
||||
drm_for_each_connector_iter(connector, &conn_iter) {
|
||||
if (!connector->state || connector->state->crtc != crtc)
|
||||
continue;
|
||||
|
||||
aconn = to_amdgpu_dm_connector(connector);
|
||||
break;
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
if (!aconn) {
|
||||
DRM_DEBUG_DRIVER("No amd connector matching CRTC-%d\n", crtc->index);
|
||||
mutex_unlock(&adev->dm.dc_lock);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
aux = &aconn->dm_dp_aux.aux;
|
||||
|
||||
if (!aux) {
|
||||
DRM_DEBUG_DRIVER("No dp aux for amd connector\n");
|
||||
mutex_unlock(&adev->dm.dc_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (dm_is_crc_source_crtc(source)) {
|
||||
if (!dc_stream_configure_crc(stream_state->ctx->dc, stream_state,
|
||||
enable, enable)) {
|
||||
mutex_unlock(&adev->dm.dc_lock);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* configure dithering */
|
||||
if (!dm_need_crc_dither(source))
|
||||
dc_stream_set_dither_option(stream_state, DITHER_OPTION_TRUN8);
|
||||
else if (!dm_need_crc_dither(crtc_state->crc_src))
|
||||
dc_stream_set_dither_option(stream_state, DITHER_OPTION_DEFAULT);
|
||||
|
||||
mutex_unlock(&adev->dm.dc_lock);
|
||||
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
|
||||
@@ -176,11 +234,15 @@ 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)
|
||||
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) {
|
||||
@@ -188,7 +250,8 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
|
||||
if (dm_is_crc_source_dprx(source)) {
|
||||
if (drm_dp_stop_crc(aux)) {
|
||||
DRM_DEBUG_DRIVER("dp stop crc failed\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,7 +260,14 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
|
||||
|
||||
/* Reset crc_skipped on dm state */
|
||||
crtc_state->crc_skip_count = 0;
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
if (commit)
|
||||
drm_crtc_commit_put(commit);
|
||||
|
||||
drm_modeset_unlock(&crtc->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
#ifndef AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_
|
||||
#define AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_
|
||||
|
||||
struct drm_crtc;
|
||||
struct dm_crtc_state;
|
||||
|
||||
enum amdgpu_dm_pipe_crc_source {
|
||||
AMDGPU_DM_PIPE_CRC_SOURCE_NONE = 0,
|
||||
AMDGPU_DM_PIPE_CRC_SOURCE_CRTC,
|
||||
@@ -44,6 +47,9 @@ static inline bool amdgpu_dm_is_valid_crc_source(enum amdgpu_dm_pipe_crc_source
|
||||
|
||||
/* amdgpu_dm_crc.c */
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
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);
|
||||
int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name);
|
||||
int amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc,
|
||||
const char *src_name,
|
||||
|
||||
@@ -1053,9 +1053,33 @@ static int target_backlight_read(struct seq_file *m, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mst_topo(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct amdgpu_dm_connector *aconnector;
|
||||
|
||||
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||
drm_for_each_connector_iter(connector, &conn_iter) {
|
||||
if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
|
||||
continue;
|
||||
|
||||
aconnector = to_amdgpu_dm_connector(connector);
|
||||
|
||||
seq_printf(m, "\nMST topology for connector %d\n", aconnector->connector_id);
|
||||
drm_dp_mst_dump_topology(m, &aconnector->mst_mgr);
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_info_list amdgpu_dm_debugfs_list[] = {
|
||||
{"amdgpu_current_backlight_pwm", ¤t_backlight_read},
|
||||
{"amdgpu_target_backlight_pwm", &target_backlight_read},
|
||||
{"amdgpu_mst_topology", &mst_topo},
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -548,7 +548,9 @@ bool dm_helpers_dp_write_dsc_enable(
|
||||
bool enable
|
||||
)
|
||||
{
|
||||
return false;
|
||||
uint8_t enable_dsc = enable ? 1 : 0;
|
||||
|
||||
return dm_helpers_dp_write_dpcd(ctx, stream->sink->link, DP_DSC_ENABLE, &enable_dsc, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user