mirror of
https://github.com/torvalds/linux.git
synced 2026-04-21 16:23:59 -04:00
Merge tag 'drm-misc-next-2019-06-05' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for v5.3: UAPI Changes: Cross-subsystem Changes: - Add devicetree bindings for new panels. - Convert allwinner's DT bindings to a schema. - Drop video/hdmi static functions from kernel docs. - Discard old fence when reserving space in reservation_object_get_fences_rcu. Core Changes: - Add missing -ENOMEM handling in edid loading. - Fix null pointer deref in scheduler. - Header cleanups, making them self-contained. - Remove drmP.h inclusion from core. - Fix make htmldocs warning in scheduler and HDR metadata. - Fix a few warnings in the uapi header and add a doc section for it. - Small MST sideband error handling fix. - Clarify userspace review requirements. - Clarify implicit/explicit fencing in docs. - Flush output polling on shutdown. Driver Changes: - Small cleanups to stm. - Add new driver for ST-Ericsson MCDE - Kconfig fix for meson HDMI. - Add support for Armadeus ST0700 Adapt panel. - Add KOE tx14d24vm1bpa panel. - Update timings for st7701. - Fix compile error in mcde. - Big series of tc358767 fixes, and enabling support for IRQ and HPD handling. - Assorted fixes to sii902x, and implementing HDMI audio support. - Enable HDR metadata support on amdgpu. - Assorted fixes to atmel-hlcdc, and add sam9x60 LCD controller support. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/6c43ffa9-11ff-5354-d772-c20fd4d1e3d9@linux.intel.com
This commit is contained in:
@@ -3875,6 +3875,128 @@ fail:
|
||||
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(&frame, state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
len = hdmi_drm_infoframe_pack_only(&frame, 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(&out->sb[i], &buf[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, &hdr_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 from
|
||||
* 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 =
|
||||
!old_con_state->hdr_output_metadata ||
|
||||
!new_con_state->hdr_output_metadata;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs
|
||||
amdgpu_dm_connector_helper_funcs = {
|
||||
/*
|
||||
@@ -3885,6 +4007,7 @@ amdgpu_dm_connector_helper_funcs = {
|
||||
*/
|
||||
.get_modes = get_modes,
|
||||
.mode_valid = amdgpu_dm_connector_mode_valid,
|
||||
.atomic_check = amdgpu_dm_connector_atomic_check,
|
||||
};
|
||||
|
||||
static void dm_crtc_helper_disable(struct drm_crtc *crtc)
|
||||
@@ -4693,6 +4816,10 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
|
||||
if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
|
||||
connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
|
||||
connector_type == DRM_MODE_CONNECTOR_eDP) {
|
||||
drm_object_attach_property(
|
||||
&aconnector->base.base,
|
||||
dm->ddev->mode_config.hdr_output_metadata_property, 0);
|
||||
|
||||
drm_connector_attach_vrr_capable_property(
|
||||
&aconnector->base);
|
||||
}
|
||||
@@ -5781,7 +5908,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(&dummy_updates, 0, sizeof(dummy_updates));
|
||||
memset(&stream_update, 0, sizeof(stream_update));
|
||||
@@ -5798,11 +5927,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(&dm_new_con_state->base.crtc->mode,
|
||||
dm_new_con_state, (struct dc_stream_state *)dm_new_crtc_state->stream);
|
||||
|
||||
@@ -5810,12 +5947,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 = &dm_new_crtc_state->abm_level;
|
||||
}
|
||||
|
||||
if (hdr_changed) {
|
||||
fill_hdr_info_packet(new_con_state, &hdr_packet);
|
||||
stream_update.hdr_static_metadata = &hdr_packet;
|
||||
}
|
||||
|
||||
status = dc_stream_get_status(dm_new_crtc_state->stream);
|
||||
WARN_ON(!status);
|
||||
WARN_ON(!status->plane_count);
|
||||
@@ -6161,6 +6303,11 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
|
||||
|
||||
dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
|
||||
|
||||
ret = fill_hdr_info_packet(drm_new_conn_state,
|
||||
&new_stream->hdr_static_metadata);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (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;
|
||||
|
||||
Reference in New Issue
Block a user