Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3186afef authored by Prabhanjan Kandula's avatar Prabhanjan Kandula Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm: atomic seamless connector change



Handle dynamic connector attach or detach of additional
connector on crtc. Avoid full modeset disable and enable
if multiple connectors connected to single CRTC. It allows
seamless handling of usecase like concurrent writeback.
Attempt to keep existing seamless mode checks intact.

Change-Id: Ia8ab0ef27400f2ba08a7d2dc6984820f3c956231
Signed-off-by: default avatarPrabhanjan Kandula <pkandula@codeaurora.org>
parent daea63ba
Loading
Loading
Loading
Loading
+87 −20
Original line number Diff line number Diff line
/*
 * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
 * Copyright (C) 2014 Red Hat
 * Author: Rob Clark <robdclark@gmail.com>
 *
@@ -25,6 +25,8 @@
#include "msm_fence.h"
#include "sde_trace.h"

#define MULTIPLE_CONN_DETECTED(x) (x > 1)

struct msm_commit {
	struct drm_device *dev;
	struct drm_atomic_state *state;
@@ -111,6 +113,66 @@ static void commit_destroy(struct msm_commit *c)
		kfree(c);
}

static inline bool _msm_seamless_for_crtc(struct drm_atomic_state *state,
			struct drm_crtc_state *crtc_state, bool enable)
{
	struct drm_connector *connector = NULL;
	struct drm_connector_state  *conn_state = NULL;
	int i = 0;
	int conn_cnt = 0;

	if (msm_is_mode_seamless(&crtc_state->mode) ||
		msm_is_mode_seamless_vrr(&crtc_state->adjusted_mode))
		return true;

	if (msm_is_mode_seamless_dms(&crtc_state->adjusted_mode) && !enable)
		return true;

	if (!crtc_state->mode_changed && crtc_state->connectors_changed) {
		for_each_connector_in_state(state, connector, conn_state, i) {
			if ((conn_state->crtc == crtc_state->crtc) ||
					(connector->state->crtc ==
					 crtc_state->crtc))
				conn_cnt++;

			if (MULTIPLE_CONN_DETECTED(conn_cnt))
				return true;
		}
	}

	return false;
}

static inline bool _msm_seamless_for_conn(struct drm_connector *connector,
		struct drm_connector_state *old_conn_state, bool enable)
{
	if (!old_conn_state || !old_conn_state->crtc)
		return false;

	if (!old_conn_state->crtc->state->mode_changed &&
			!old_conn_state->crtc->state->active_changed &&
			old_conn_state->crtc->state->connectors_changed) {
		if (old_conn_state->crtc == connector->state->crtc)
			return true;
	}

	if (enable)
		return false;

	if (msm_is_mode_seamless(&connector->encoder->crtc->state->mode))
		return true;

	if (msm_is_mode_seamless_vrr(
			&connector->encoder->crtc->state->adjusted_mode))
		return true;

	if (msm_is_mode_seamless_dms(
			&connector->encoder->crtc->state->adjusted_mode))
		return true;

	return false;
}

static void msm_atomic_wait_for_commit_done(
		struct drm_device *dev,
		struct drm_atomic_state *old_state)
@@ -169,14 +231,7 @@ msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
		if (WARN_ON(!encoder))
			continue;

		if (msm_is_mode_seamless(
			&connector->encoder->crtc->state->mode) ||
			msm_is_mode_seamless_vrr(
			&connector->encoder->crtc->state->adjusted_mode))
			continue;

		if (msm_is_mode_seamless_dms(
			&connector->encoder->crtc->state->adjusted_mode))
		if (_msm_seamless_for_conn(connector, old_conn_state, false))
			continue;

		funcs = encoder->helper_private;
@@ -218,11 +273,7 @@ msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
		if (!old_crtc_state->active)
			continue;

		if (msm_is_mode_seamless(&crtc->state->mode) ||
			msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode))
			continue;

		if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode))
		if (_msm_seamless_for_crtc(old_state, crtc->state, false))
			continue;

		funcs = crtc->helper_private;
@@ -281,8 +332,14 @@ msm_crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
		mode = &new_crtc_state->mode;
		adjusted_mode = &new_crtc_state->adjusted_mode;

		if (!new_crtc_state->mode_changed)
		if (!new_crtc_state->mode_changed &&
				new_crtc_state->connectors_changed) {
			if (_msm_seamless_for_conn(connector,
					old_conn_state, false))
				continue;
		} else if (!new_crtc_state->mode_changed) {
			continue;
		}

		DRM_DEBUG_ATOMIC("modeset on [ENCODER:%d:%s]\n",
				 encoder->base.id, encoder->name);
@@ -362,9 +419,7 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
		if (!new_crtc_state->active)
			continue;

		if (msm_is_mode_seamless(&new_crtc_state->mode) ||
				msm_is_mode_seamless_vrr(
				&new_crtc_state->adjusted_mode))
		if (_msm_seamless_for_crtc(old_state, crtc->state, true))
			continue;

		funcs = crtc->helper_private;
@@ -389,6 +444,7 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
			new_conn_state, i) {
		const struct drm_encoder_helper_funcs *funcs;
		struct drm_encoder *encoder;
		struct drm_connector_state *old_conn_state;

		if (!new_conn_state->best_encoder)
			continue;
@@ -398,7 +454,12 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
					new_conn_state->crtc->state))
			continue;

		encoder = new_conn_state->best_encoder;
		old_conn_state = drm_atomic_get_old_connector_state(
				old_state, connector);
		if (_msm_seamless_for_conn(connector, old_conn_state, true))
			continue;

		encoder = connector->state->best_encoder;
		funcs = encoder->helper_private;

		DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n",
@@ -437,6 +498,7 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
	for_each_new_connector_in_state(old_state, connector,
			new_conn_state, i) {
		struct drm_encoder *encoder;
		struct drm_connector_state *old_conn_state;

		if (!new_conn_state->best_encoder)
			continue;
@@ -446,7 +508,12 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
				    new_conn_state->crtc->state))
			continue;

		encoder = new_conn_state->best_encoder;
		old_conn_state = drm_atomic_get_old_connector_state(
				old_state, connector);
		if (_msm_seamless_for_conn(connector, old_conn_state, true))
			continue;

		encoder = connector->state->best_encoder;

		DRM_DEBUG_ATOMIC("bridge enable enabling [ENCODER:%d:%s]\n",
				 encoder->base.id, encoder->name);