From 6778948f9de86c3cfaf36725a7c87dcff9ba247f Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 08:20:59 +0000
Subject: [PATCH] kernel_5.10 no rt

---
 kernel/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c |   64 +++++++++++++++++++++++++------
 1 files changed, 51 insertions(+), 13 deletions(-)

diff --git a/kernel/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/kernel/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c
index 067314d..dcd49b6 100644
--- a/kernel/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c
+++ b/kernel/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c
@@ -45,11 +45,11 @@
 #include <media/videobuf2-v4l2.h>
 #include <soc/rockchip/rockchip-system-status.h>
 #include <sound/hdmi-codec.h>
+#include <linux/rk_hdmirx_class.h>
 #include "rk_hdmirx.h"
 #include "rk_hdmirx_cec.h"
 #include "rk_hdmirx_hdcp.h"
 
-static struct class *hdmirx_class;
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "debug level (0-3)");
@@ -269,6 +269,7 @@
 static void hdmirx_cancel_cpu_limit_freq(struct rk_hdmirx_dev *hdmirx_dev);
 static void hdmirx_plugout(struct rk_hdmirx_dev *hdmirx_dev);
 static void process_signal_change(struct rk_hdmirx_dev *hdmirx_dev);
+static void hdmirx_interrupts_setup(struct rk_hdmirx_dev *hdmirx_dev, bool en);
 
 static u8 edid_init_data_340M[] = {
 	0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
@@ -529,6 +530,16 @@
 	struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev;
 	u32 dma_cfg1;
 
+	if (port_no_link(hdmirx_dev)) {
+		v4l2_err(v4l2_dev, "%s port has no link!\n", __func__);
+		return -ENOLINK;
+	}
+
+	if (signal_not_lock(hdmirx_dev)) {
+		v4l2_err(v4l2_dev, "%s signal is not locked!\n", __func__);
+		return -ENOLCK;
+	}
+
 	*timings = hdmirx_dev->timings;
 	dma_cfg1 = hdmirx_readl(hdmirx_dev, DMA_CONFIG1);
 	v4l2_dbg(1, debug, v4l2_dev, "%s: pix_fmt: %s, DMA_CONFIG1:%#x\n",
@@ -615,8 +626,10 @@
 static void hdmirx_get_pix_fmt(struct rk_hdmirx_dev *hdmirx_dev)
 {
 	u32 val;
+	int timeout = 10;
 	struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev;
 
+try_loop:
 	val = hdmirx_readl(hdmirx_dev, DMA_STATUS11);
 	hdmirx_dev->pix_fmt = val & HDMIRX_FORMAT_MASK;
 
@@ -635,11 +648,16 @@
 		break;
 
 	default:
+		if (timeout-- > 0) {
+			usleep_range(200 * 1000, 200 * 1010);
+			v4l2_err(v4l2_dev, "%s: get format failed, read again!\n", __func__);
+			goto try_loop;
+		}
+		hdmirx_dev->pix_fmt = HDMIRX_RGB888;
+		hdmirx_dev->cur_fmt_fourcc = V4L2_PIX_FMT_BGR24;
 		v4l2_err(v4l2_dev,
 			"%s: err pix_fmt: %d, set RGB888 as default\n",
 			__func__, hdmirx_dev->pix_fmt);
-		hdmirx_dev->pix_fmt = HDMIRX_RGB888;
-		hdmirx_dev->cur_fmt_fourcc = V4L2_PIX_FMT_BGR24;
 		break;
 	}
 
@@ -880,9 +898,12 @@
 	struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev;
 	u32 last_w, last_h;
 	struct v4l2_bt_timings *bt = &timings->bt;
+	enum hdmirx_pix_fmt last_fmt;
 
 	last_w = 0;
 	last_h = 0;
+	last_fmt = HDMIRX_RGB888;
+
 	for (i = 0; i < try_cnt; i++) {
 		ret = hdmirx_get_detected_timings(hdmirx_dev, timings, from_dma);
 
@@ -891,7 +912,8 @@
 			last_h = bt->height;
 		}
 
-		if (ret || (last_w != bt->width) || (last_h != bt->height))
+		if (ret || (last_w != bt->width) || (last_h != bt->height)
+			|| (last_fmt != hdmirx_dev->pix_fmt))
 			cnt = 0;
 		else
 			cnt++;
@@ -901,6 +923,7 @@
 
 		last_w = bt->width;
 		last_h = bt->height;
+		last_fmt = hdmirx_dev->pix_fmt;
 		usleep_range(10*1000, 10*1100);
 	}
 
@@ -1545,7 +1568,7 @@
 	}
 
 	hdmirx_reset_dma(hdmirx_dev);
-	usleep_range(200*1000, 200*1010);
+	usleep_range(500*1000, 500*1010);
 	hdmirx_format_change(hdmirx_dev);
 
 	return 0;
@@ -2349,6 +2372,7 @@
 			FIFO_UNDERFLOW_INT_EN |
 			HDMIRX_AXI_ERROR_INT_EN, 0);
 	hdmirx_reset_dma(hdmirx_dev);
+	hdmirx_interrupts_setup(hdmirx_dev, false);
 	v4l2_event_queue(&stream->vdev, &evt_signal_lost);
 	if (hdmirx_dev->hdcp && hdmirx_dev->hdcp->hdcp_stop)
 		hdmirx_dev->hdcp->hdcp_stop(hdmirx_dev->hdcp);
@@ -2459,13 +2483,28 @@
 	hdmirx_writel(hdmirx_dev, MAINUNIT_2_INT_FORCE, 0x0);
 }
 
+/*
+ * In the normal preview, some scenarios will trigger the change interrupt
+ * by mistake, and the trigger source of the interrupt needs to be detected
+ * to avoid the problem.
+ */
 static void pkt_0_int_handler(struct rk_hdmirx_dev *hdmirx_dev,
 		int status, bool *handled)
 {
 	struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev;
+	u32 pre_fmt_fourcc = hdmirx_dev->cur_fmt_fourcc;
+	u32 pre_color_range = hdmirx_dev->cur_color_range;
+	u32 pre_color_space = hdmirx_dev->cur_color_space;
 
 	if ((status & PKTDEC_AVIIF_CHG_IRQ)) {
-		process_signal_change(hdmirx_dev);
+		hdmirx_get_color_range(hdmirx_dev);
+		hdmirx_get_color_space(hdmirx_dev);
+		hdmirx_get_pix_fmt(hdmirx_dev);
+		if (hdmirx_dev->cur_fmt_fourcc != pre_fmt_fourcc ||
+		    hdmirx_dev->cur_color_range != pre_color_range ||
+		    hdmirx_dev->cur_color_space != pre_color_space) {
+			process_signal_change(hdmirx_dev);
+		}
 		v4l2_dbg(2, debug, v4l2_dev, "%s: ptk0_st:%#x\n",
 				__func__, status);
 		*handled = true;
@@ -3158,7 +3197,7 @@
 							struct rk_hdmirx_dev,
 							delayed_work_audio);
 	struct hdmirx_audiostate *as = &hdmirx_dev->audio_state;
-	u32 fs_audio, ch_audio;
+	u32 fs_audio, ch_audio, sample_flat;
 	int cur_state, init_state, pre_state, fifo_status2;
 	unsigned long delay = 200;
 
@@ -3223,6 +3262,10 @@
 		}
 	}
 	as->pre_state = cur_state;
+
+	sample_flat = hdmirx_readl(hdmirx_dev, AUDIO_PROC_STATUS1) & AUD_SAMPLE_FLAT;
+	hdmirx_update_bits(hdmirx_dev, AUDIO_PROC_CONFIG0, I2S_EN, sample_flat ? 0 : I2S_EN);
+
 exit:
 	schedule_delayed_work_on(hdmirx_dev->bound_cpu,
 			&hdmirx_dev->delayed_work_audio,
@@ -3243,7 +3286,6 @@
 	plugin = tx_5v_power_present(hdmirx_dev);
 	v4l2_dbg(1, debug, v4l2_dev, "%s: plugin:%d\n", __func__, plugin);
 	if (plugin) {
-		hdmirx_interrupts_setup(hdmirx_dev, false);
 		hdmirx_submodule_init(hdmirx_dev);
 		hdmirx_update_bits(hdmirx_dev, SCDC_CONFIG, POWERPROVIDED,
 					POWERPROVIDED);
@@ -4280,7 +4322,7 @@
 	if (ret)
 		goto err_unreg_video_dev;
 
-	hdmirx_dev->classdev = device_create_with_groups(hdmirx_class,
+	hdmirx_dev->classdev = device_create_with_groups(rk_hdmirx_class(),
 							 dev, MKDEV(0, 0),
 							 hdmirx_dev,
 							 hdmirx_groups,
@@ -4438,9 +4480,6 @@
 
 static int __init hdmirx_init(void)
 {
-	hdmirx_class = class_create(THIS_MODULE, "hdmirx");
-	if (IS_ERR(hdmirx_class))
-		return PTR_ERR(hdmirx_class);
 	return platform_driver_register(&hdmirx_driver);
 }
 module_init(hdmirx_init);
@@ -4448,7 +4487,6 @@
 static void __exit hdmirx_exit(void)
 {
 	platform_driver_unregister(&hdmirx_driver);
-	class_destroy(hdmirx_class);
 }
 module_exit(hdmirx_exit);
 

--
Gitblit v1.6.2