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

Commit 7ab31587 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "disp: msm: dp: add support for Trusted UI transitions"

parents ff5233ee f3b2c5f8
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -397,6 +397,11 @@ static int dp_audio_info_setup(struct platform_device *pdev,
		return rc;
	}

	if (audio->dp_audio.tui_active) {
		DP_DEBUG("TUI session active\n");
		return 0;
	}

	mutex_lock(&audio->ops_lock);

	audio->channels = params->num_of_channels;
@@ -495,6 +500,11 @@ static void dp_audio_teardown_done(struct platform_device *pdev)
	if (IS_ERR(audio))
		return;

	if (audio->dp_audio.tui_active) {
		DP_DEBUG("TUI session active\n");
		return;
	}

	mutex_lock(&audio->ops_lock);
	dp_audio_enable(audio, false);
	mutex_unlock(&audio->ops_lock);
+7 −3
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _DP_AUDIO_H_
@@ -15,15 +15,18 @@
 * struct dp_audio
 * @lane_count: number of lanes configured in current session
 * @bw_code: link rate's bandwidth code for current session
 * @tui_active: set to true if TUI is active in the system
 */
struct dp_audio {
	u32 lane_count;
	u32 bw_code;
	bool tui_active;

	/**
	 * on()
	 *
	 * Enables the audio by notifying the user module.
	 * Notifies user mode clients that DP is powered on, and that audio
	 * playback can start on the external display.
	 *
	 * @dp_audio: an instance of struct dp_audio.
	 *
@@ -34,7 +37,8 @@ struct dp_audio {
	/**
	 * off()
	 *
	 * Disables the audio by notifying the user module.
	 * Notifies user mode clients that DP is shutting down, and audio
	 * playback should be stopped on the external display.
	 *
	 * @dp_audio: an instance of struct dp_audio.
	 *
+127 −8
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ enum dp_display_states {
	DP_STATE_ABORTED                = BIT(8),
	DP_STATE_HDCP_ABORTED           = BIT(9),
	DP_STATE_SRC_PWRDN              = BIT(10),
	DP_STATE_TUI_ACTIVE             = BIT(11),
};

static char *dp_display_state_name(enum dp_display_states state)
@@ -117,6 +118,10 @@ static char *dp_display_state_name(enum dp_display_states state)
		len += scnprintf(buf + len, sizeof(buf) - len, "|%s|",
			"SRC_PWRDN");

	if (state & DP_STATE_TUI_ACTIVE)
		len += scnprintf(buf + len, sizeof(buf) - len, "|%s|",
			"TUI_ACTIVE");

	if (!strlen(buf))
		return "DISCONNECTED";

@@ -669,6 +674,74 @@ static int dp_display_initialize_hdcp(struct dp_display_private *dp)
	return rc;
}

static void dp_display_pause_audio(struct dp_display_private *dp, bool pause)
{
	struct dp_panel *dp_panel;
	int idx;

	for (idx = DP_STREAM_0; idx < DP_STREAM_MAX; idx++) {
		if (!dp->active_panels[idx])
			continue;
		dp_panel = dp->active_panels[idx];

		if (dp_panel->audio_supported)
			dp_panel->audio->tui_active = pause;
	}
}

static int dp_display_pre_hw_release(void *data)
{
	struct dp_display_private *dp;
	struct dp_display *dp_display = data;

	SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY);

	if (!dp_display)
		return -EINVAL;

	dp = container_of(dp_display, struct dp_display_private, dp_display);

	mutex_lock(&dp->session_lock);

	dp_display_state_add(DP_STATE_TUI_ACTIVE);
	cancel_work_sync(&dp->connect_work);
	cancel_work_sync(&dp->attention_work);
	flush_workqueue(dp->wq);

	dp_display_pause_audio(dp, true);
	disable_irq(dp->irq);

	mutex_unlock(&dp->session_lock);

	SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT);
	return 0;
}

static int dp_display_post_hw_acquire(void *data)
{
	struct dp_display_private *dp;
	struct dp_display *dp_display = data;

	SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY);

	if (!dp_display)
		return -EINVAL;

	dp = container_of(dp_display, struct dp_display_private, dp_display);

	mutex_lock(&dp->session_lock);

	dp_display_state_remove(DP_STATE_TUI_ACTIVE);
	dp_display_pause_audio(dp, false);
	enable_irq(dp->irq);

	mutex_unlock(&dp->session_lock);

	SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT);
	return 0;
}


static int dp_display_bind(struct device *dev, struct device *master,
		void *data)
{
@@ -676,6 +749,10 @@ static int dp_display_bind(struct device *dev, struct device *master,
	struct dp_display_private *dp;
	struct drm_device *drm;
	struct platform_device *pdev = to_platform_device(dev);
	struct msm_vm_ops vm_event_ops = {
		.vm_pre_hw_release = dp_display_pre_hw_release,
		.vm_post_hw_acquire = dp_display_post_hw_acquire,
	};

	if (!dev || !pdev || !master) {
		DP_ERR("invalid param(s), dev %pK, pdev %pK, master %pK\n",
@@ -695,6 +772,8 @@ static int dp_display_bind(struct device *dev, struct device *master,

	dp->dp_display.drm_dev = drm;
	dp->priv = drm->dev_private;
	msm_register_vm_event(master, dev, &vm_event_ops,
			(void *)&dp->dp_display);
end:
	return rc;
}
@@ -829,6 +908,15 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp)
	reinit_completion(&dp->notification_comp);
	dp_display_send_hpd_event(dp);

	/*
	 * Skip the wait if TUI is active considering that the user mode will
	 * not act on the notification until after the TUI session is over.
	 */
	if (dp_display_state_is(DP_STATE_TUI_ACTIVE)) {
		dp_display_state_log("[TUI is active, skipping wait]");
		goto skip_wait;
	}

	if (hpd && dp->mst.mst_active)
		goto skip_wait;

@@ -1211,26 +1299,30 @@ static int dp_display_usbpd_configure_cb(struct device *dev)

	if (!dev) {
		DP_ERR("invalid dev\n");
		rc = -EINVAL;
		goto end;
		return -EINVAL;
	}

	dp = dev_get_drvdata(dev);
	if (!dp) {
		DP_ERR("no driver data found\n");
		rc = -ENODEV;
		goto end;
		return -ENODEV;
	}

	if (!dp->debug->sim_mode && !dp->parser->no_aux_switch
	    && !dp->parser->gpio_aux_switch) {
		rc = dp->aux->aux_switch(dp->aux, true, dp->hpd->orientation);
		if (rc)
			goto end;
			return rc;
	}

	mutex_lock(&dp->session_lock);

	if (dp_display_state_is(DP_STATE_TUI_ACTIVE)) {
		dp_display_state_log("[TUI is active]");
		mutex_unlock(&dp->session_lock);
		return 0;
	}

	dp_display_state_remove(DP_STATE_ABORTED);
	dp_display_state_add(DP_STATE_CONFIGURED);

@@ -1242,8 +1334,8 @@ static int dp_display_usbpd_configure_cb(struct device *dev)
	else
		dp->process_hpd_connect = true;
	mutex_unlock(&dp->session_lock);
end:
	return rc;

	return 0;
}

static int dp_display_stream_pre_disable(struct dp_display_private *dp,
@@ -1291,6 +1383,11 @@ static void dp_display_clean(struct dp_display_private *dp)

	SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY, dp->state);

	if (dp_display_state_is(DP_STATE_TUI_ACTIVE)) {
		DP_WARN("TUI is active\n");
		return;
	}

	if (dp_display_is_hdcp_enabled(dp) &&
			status->hdcp_state != HDCP_STATE_INACTIVE) {
		cancel_delayed_work_sync(&dp->hdcp_cb_work);
@@ -1599,7 +1696,24 @@ static int dp_display_usbpd_attention_cb(struct device *dev)

	if (!dp->hpd->hpd_high) {
		dp_display_disconnect_sync(dp);
	} else if ((dp->hpd->hpd_irq && dp_display_state_is(DP_STATE_READY)) ||
		return 0;
	}

	/*
	 * Ignore all the attention messages except HPD LOW when TUI is
	 * active, so user mode can be notified of the disconnect event. This
	 * allows user mode to tear down the control path after the TUI
	 * session is over. Ideally this should never happen, but on the off
	 * chance that there is a race condition in which there is a IRQ HPD
	 * during tear down of DP at TUI start then this check might help avoid
	 * a potential issue accessing registers in attention processing.
	 */
	if (dp_display_state_is(DP_STATE_TUI_ACTIVE)) {
		DP_WARN("TUI is active\n");
		return 0;
	}

	if ((dp->hpd->hpd_irq && dp_display_state_is(DP_STATE_READY)) ||
			dp->debug->mst_hpd_sim) {
		queue_work(dp->wq, &dp->attention_work);
		complete_all(&dp->attention_comp);
@@ -1620,6 +1734,11 @@ static void dp_display_connect_work(struct work_struct *work)
	struct dp_display_private *dp = container_of(work,
			struct dp_display_private, connect_work);

	if (dp_display_state_is(DP_STATE_TUI_ACTIVE)) {
		dp_display_state_log("[TUI is active]");
		return;
	}

	if (dp_display_state_is(DP_STATE_ABORTED)) {
		DP_WARN("HPD off requested\n");
		return;