From e3e12f52b214121840b44c91de5b3e5af5d3eb84 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 06 Nov 2023 03:04:41 +0000
Subject: [PATCH] rk3568 rt init

---
 kernel/sound/soc/codecs/hdmi-codec.c |   67 +++++++++++++++++++++++++++++++--
 1 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/kernel/sound/soc/codecs/hdmi-codec.c b/kernel/sound/soc/codecs/hdmi-codec.c
index 0cb4976..93fa207 100644
--- a/kernel/sound/soc/codecs/hdmi-codec.c
+++ b/kernel/sound/soc/codecs/hdmi-codec.c
@@ -14,6 +14,7 @@
  */
 #include <linux/module.h>
 #include <linux/string.h>
+#include <linux/extcon-provider.h>
 #include <sound/core.h>
 #include <sound/jack.h>
 #include <sound/pcm.h>
@@ -277,6 +278,11 @@
 	  .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC },
 };
 
+static const unsigned int hdmi_extcon_cable[] = {
+	EXTCON_DISP_HDMI_AUDIO,
+	EXTCON_NONE,
+};
+
 struct hdmi_codec_priv {
 	struct hdmi_codec_pdata hcd;
 	struct snd_soc_dai_driver *daidrv;
@@ -288,6 +294,7 @@
 	unsigned int chmap_idx;
 	unsigned int mode;
 	struct snd_soc_jack *jack;
+	struct extcon_dev *edev;
 	unsigned int jack_status;
 };
 
@@ -498,7 +505,8 @@
 	WARN_ON(hcp->current_stream != substream);
 
 	hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
-	hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data);
+	if (hcp->hcd.ops->audio_shutdown)
+		hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data);
 
 	mutex_lock(&hcp->current_stream_lock);
 	hcp->current_stream = NULL;
@@ -774,10 +782,48 @@
 {
 	struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);
 
-	if (plugged)
+	if (plugged) {
 		hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
-	else
+		extcon_set_state_sync(hcp->edev,
+				      EXTCON_DISP_HDMI_AUDIO, true);
+	} else {
 		hdmi_codec_jack_report(hcp, 0);
+		extcon_set_state_sync(hcp->edev,
+				      EXTCON_DISP_HDMI_AUDIO, false);
+	}
+
+	mutex_lock(&hcp->current_stream_lock);
+	if (hcp->current_stream) {
+		/*
+		 * Workaround for HDMIIN and HDMIOUT plug-{in,out} when streaming.
+		 *
+		 * Actually, we should do stop stream both for HDMI_{OUT,IN} on
+		 * plug-{out,in} event. but for better experience and depop stream,
+		 * we optimize as follows:
+		 *
+		 * a) Do stop stream for HDMIIN on plug-out when streaming.
+		 * because HDMIIN work as SLAVE mode, CLK lost after HDMI cable
+		 * plugged out which will make stream stuck until ALSA timeout(10s).
+		 * so, for better experience, we should stop stream at the moment.
+		 *
+		 * b) Do stop stream for HDMIOUT on plug-in when streaming.
+		 * because HDMIOUT work as MASTER mode, there is no clk-issue like
+		 * HDMIIN, but, on HDR situation, HDMI will be reconfigured which
+		 * make HDMI audio configure lost, especially for NLPCM/HBR bitstream
+		 * which require IEC937 packet alignment, so, for this situation,
+		 * we stop stream to notify user to re-open and configure sound card
+		 * and then go on streaming.
+		 */
+		int stream = hcp->current_stream->stream;
+
+		if (stream == SNDRV_PCM_STREAM_PLAYBACK && plugged)
+			snd_pcm_stop(hcp->current_stream, SNDRV_PCM_STATE_SETUP);
+		else if (stream == SNDRV_PCM_STREAM_CAPTURE && !plugged)
+			snd_pcm_stop(hcp->current_stream, SNDRV_PCM_STATE_DISCONNECTED);
+
+		dev_dbg(dev, "stream[%d]: %s\n", stream, plugged ? "plug in" : "plug out");
+	}
+	mutex_unlock(&hcp->current_stream_lock);
 }
 
 static int hdmi_codec_set_jack(struct snd_soc_component *component,
@@ -884,8 +930,7 @@
 	}
 
 	dai_count = hcd->i2s + hcd->spdif;
-	if (dai_count < 1 || !hcd->ops || !hcd->ops->hw_params ||
-	    !hcd->ops->audio_shutdown) {
+	if (dai_count < 1 || !hcd->ops || !hcd->ops->hw_params) {
 		dev_err(dev, "%s: Invalid parameters\n", __func__);
 		return -EINVAL;
 	}
@@ -916,6 +961,18 @@
 
 	dev_set_drvdata(dev, hcp);
 
+	hcp->edev = devm_extcon_dev_allocate(&pdev->dev, hdmi_extcon_cable);
+	if (IS_ERR(hcp->edev)) {
+		dev_err(&pdev->dev, "Failed to allocate extcon device\n");
+		return -ENOMEM;
+	}
+
+	ret = devm_extcon_dev_register(&pdev->dev, hcp->edev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register extcon device\n");
+		return ret;
+	}
+
 	ret = devm_snd_soc_register_component(dev, &hdmi_driver, hcp->daidrv,
 				     dai_count);
 	if (ret) {

--
Gitblit v1.6.2