diff mbox series

[v9] drm/bridge: it6505: This patch fixes hibernate to resume no display issue

Message ID 20240517021654.1034218-1-kuro.chung@ite.com.tw (mailing list archive)
State New, archived
Headers show
Series [v9] drm/bridge: it6505: This patch fixes hibernate to resume no display issue | expand

Commit Message

kuro May 17, 2024, 2:16 a.m. UTC
From: Kuro Chung <kuro.chung@ite.com.tw>

This patch added a FIFO reset bit for input video. When system power resume,
the TTL input of it6505 may get some noise before video signal stable
and the hardware function reset is required.
But the input FIFO reset will also trigger error interrupts of output 
module rising.Thus, it6505 have to wait a period can clear those 
expected error interrupts caused by manual hardware reset in one 
interrupt handler calling to avoid interrupt looping.

Fixes: b5c84a9edcd4 ("drm/bridge: add it6505 driver")

---
 drivers/gpu/drm/bridge/ite-it6505.c | 73 +++++++++++++++++++----------
 1 file changed, 49 insertions(+), 24 deletions(-)

Comments

AngeloGioacchino Del Regno May 17, 2024, 10:37 a.m. UTC | #1
Il 17/05/24 04:16, kuro ha scritto:
> From: Kuro Chung <kuro.chung@ite.com.tw>
> 
> This patch added a FIFO reset bit for input video. When system power resume,
> the TTL input of it6505 may get some noise before video signal stable
> and the hardware function reset is required.
> But the input FIFO reset will also trigger error interrupts of output
> module rising.Thus, it6505 have to wait a period can clear those
> expected error interrupts caused by manual hardware reset in one
> interrupt handler calling to avoid interrupt looping.
> 
> Fixes: b5c84a9edcd4 ("drm/bridge: add it6505 driver")
> 

Your Signed-off-by tag is missing.

Regards,
Angelo

> ---
>   drivers/gpu/drm/bridge/ite-it6505.c | 73 +++++++++++++++++++----------
>   1 file changed, 49 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
> index 469157341f3ab..5703fcf4b7b00 100644
> --- a/drivers/gpu/drm/bridge/ite-it6505.c
> +++ b/drivers/gpu/drm/bridge/ite-it6505.c
> @@ -1307,9 +1307,15 @@ static void it6505_video_reset(struct it6505 *it6505)
>   	it6505_link_reset_step_train(it6505);
>   	it6505_set_bits(it6505, REG_DATA_MUTE_CTRL, EN_VID_MUTE, EN_VID_MUTE);
>   	it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_VID_CTRL_PKT, 0x00);
> -	it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, VIDEO_RESET);
> +
> +	it6505_set_bits(it6505, REG_VID_BUS_CTRL1, TX_FIFO_RESET, TX_FIFO_RESET);
> +	it6505_set_bits(it6505, REG_VID_BUS_CTRL1, TX_FIFO_RESET, 0x00);
> +
>   	it6505_set_bits(it6505, REG_501_FIFO_CTRL, RST_501_FIFO, RST_501_FIFO);
>   	it6505_set_bits(it6505, REG_501_FIFO_CTRL, RST_501_FIFO, 0x00);
> +
> +	it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, VIDEO_RESET);
> +	usleep_range(1000, 2000);
>   	it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, 0x00);
>   }
>   
> @@ -2245,12 +2251,11 @@ static void it6505_link_training_work(struct work_struct *work)
>   	if (ret) {
>   		it6505->auto_train_retry = AUTO_TRAIN_RETRY;
>   		it6505_link_train_ok(it6505);
> -		return;
>   	} else {
>   		it6505->auto_train_retry--;
> +		it6505_dump(it6505);
>   	}
>   
> -	it6505_dump(it6505);
>   }
>   
>   static void it6505_plugged_status_to_codec(struct it6505 *it6505)
> @@ -2471,31 +2476,53 @@ static void it6505_irq_link_train_fail(struct it6505 *it6505)
>   	schedule_work(&it6505->link_works);
>   }
>   
> -static void it6505_irq_video_fifo_error(struct it6505 *it6505)
> +static bool it6505_test_bit(unsigned int bit, const unsigned int *addr)
>   {
> -	struct device *dev = it6505->dev;
> -
> -	DRM_DEV_DEBUG_DRIVER(dev, "video fifo overflow interrupt");
> -	it6505->auto_train_retry = AUTO_TRAIN_RETRY;
> -	flush_work(&it6505->link_works);
> -	it6505_stop_hdcp(it6505);
> -	it6505_video_reset(it6505);
> +	return 1 & (addr[bit / BITS_PER_BYTE] >> (bit % BITS_PER_BYTE));
>   }
>   
> -static void it6505_irq_io_latch_fifo_overflow(struct it6505 *it6505)
> +static void it6505_irq_video_handler(struct it6505 *it6505, const int *int_status)
>   {
>   	struct device *dev = it6505->dev;
> +	int reg_0d, reg_int03;
>   
> -	DRM_DEV_DEBUG_DRIVER(dev, "IO latch fifo overflow interrupt");
> -	it6505->auto_train_retry = AUTO_TRAIN_RETRY;
> -	flush_work(&it6505->link_works);
> -	it6505_stop_hdcp(it6505);
> -	it6505_video_reset(it6505);
> -}
> +	/*
> +	 * When video SCDT change with video not stable,
> +	 * Or video FIFO error, need video reset
> +	 */
>   
> -static bool it6505_test_bit(unsigned int bit, const unsigned int *addr)
> -{
> -	return 1 & (addr[bit / BITS_PER_BYTE] >> (bit % BITS_PER_BYTE));
> +	if ((!it6505_get_video_status(it6505) &&
> +		(it6505_test_bit(INT_SCDT_CHANGE, (unsigned int *) int_status))) ||
> +		(it6505_test_bit(BIT_INT_IO_FIFO_OVERFLOW, (unsigned int *) int_status)) ||
> +		(it6505_test_bit(BIT_INT_VID_FIFO_ERROR, (unsigned int *) int_status))) {
> +
> +		it6505->auto_train_retry = AUTO_TRAIN_RETRY;
> +		flush_work(&it6505->link_works);
> +		it6505_stop_hdcp(it6505);
> +		it6505_video_reset(it6505);
> +
> +		usleep_range(10000, 11000);
> +
> +		/*
> +		 * Clear FIFO error IRQ to prevent fifo error -> reset loop
> +		 * HW will trigger SCDT change IRQ again when video stable
> +		 */
> +
> +		reg_int03 = it6505_read(it6505, INT_STATUS_03);
> +		reg_0d = it6505_read(it6505, REG_SYSTEM_STS);
> +
> +		reg_int03 &= (BIT(INT_VID_FIFO_ERROR) | BIT(INT_IO_LATCH_FIFO_OVERFLOW));
> +		it6505_write(it6505, INT_STATUS_03, reg_int03);
> +
> +		DRM_DEV_DEBUG_DRIVER(dev, "reg08 = 0x%02x", reg_int03);
> +		DRM_DEV_DEBUG_DRIVER(dev, "reg0D = 0x%02x", reg_0d);
> +
> +		return;
> +	}
> +
> +
> +	if (it6505_test_bit(INT_SCDT_CHANGE, (unsigned int *) int_status))
> +		it6505_irq_scdt(it6505);
>   }
>   
>   static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
> @@ -2508,15 +2535,12 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
>   	} irq_vec[] = {
>   		{ BIT_INT_HPD, it6505_irq_hpd },
>   		{ BIT_INT_HPD_IRQ, it6505_irq_hpd_irq },
> -		{ BIT_INT_SCDT, it6505_irq_scdt },
>   		{ BIT_INT_HDCP_FAIL, it6505_irq_hdcp_fail },
>   		{ BIT_INT_HDCP_DONE, it6505_irq_hdcp_done },
>   		{ BIT_INT_AUX_CMD_FAIL, it6505_irq_aux_cmd_fail },
>   		{ BIT_INT_HDCP_KSV_CHECK, it6505_irq_hdcp_ksv_check },
>   		{ BIT_INT_AUDIO_FIFO_ERROR, it6505_irq_audio_fifo_error },
>   		{ BIT_INT_LINK_TRAIN_FAIL, it6505_irq_link_train_fail },
> -		{ BIT_INT_VID_FIFO_ERROR, it6505_irq_video_fifo_error },
> -		{ BIT_INT_IO_FIFO_OVERFLOW, it6505_irq_io_latch_fifo_overflow },
>   	};
>   	int int_status[3], i;
>   
> @@ -2546,6 +2570,7 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
>   			if (it6505_test_bit(irq_vec[i].bit, (unsigned int *)int_status))
>   				irq_vec[i].handler(it6505);
>   		}
> +		it6505_irq_video_handler(it6505, (unsigned int *) int_status);
>   	}
>   
>   	pm_runtime_put_sync(dev);
Markus Elfring May 17, 2024, 6:30 p.m. UTC | #2
Please omit the word combination “This patch” from the summary phrase.


…
> But the input FIFO reset will also trigger error interrupts of output
> module rising.Thus, it6505 have to wait a period can clear those
> expected error interrupts caused by manual hardware reset in one
> interrupt handler calling to avoid interrupt looping.

Please improve this change description another bit.


…
> ---
>  drivers/gpu/drm/bridge/ite-it6505.c | 73 +++++++++++++++++++----------
…

You may present version descriptions behind the marker line.

Regards,
Markus
diff mbox series

Patch

diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
index 469157341f3ab..5703fcf4b7b00 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -1307,9 +1307,15 @@  static void it6505_video_reset(struct it6505 *it6505)
 	it6505_link_reset_step_train(it6505);
 	it6505_set_bits(it6505, REG_DATA_MUTE_CTRL, EN_VID_MUTE, EN_VID_MUTE);
 	it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_VID_CTRL_PKT, 0x00);
-	it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, VIDEO_RESET);
+
+	it6505_set_bits(it6505, REG_VID_BUS_CTRL1, TX_FIFO_RESET, TX_FIFO_RESET);
+	it6505_set_bits(it6505, REG_VID_BUS_CTRL1, TX_FIFO_RESET, 0x00);
+
 	it6505_set_bits(it6505, REG_501_FIFO_CTRL, RST_501_FIFO, RST_501_FIFO);
 	it6505_set_bits(it6505, REG_501_FIFO_CTRL, RST_501_FIFO, 0x00);
+
+	it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, VIDEO_RESET);
+	usleep_range(1000, 2000);
 	it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, 0x00);
 }
 
@@ -2245,12 +2251,11 @@  static void it6505_link_training_work(struct work_struct *work)
 	if (ret) {
 		it6505->auto_train_retry = AUTO_TRAIN_RETRY;
 		it6505_link_train_ok(it6505);
-		return;
 	} else {
 		it6505->auto_train_retry--;
+		it6505_dump(it6505);
 	}
 
-	it6505_dump(it6505);
 }
 
 static void it6505_plugged_status_to_codec(struct it6505 *it6505)
@@ -2471,31 +2476,53 @@  static void it6505_irq_link_train_fail(struct it6505 *it6505)
 	schedule_work(&it6505->link_works);
 }
 
-static void it6505_irq_video_fifo_error(struct it6505 *it6505)
+static bool it6505_test_bit(unsigned int bit, const unsigned int *addr)
 {
-	struct device *dev = it6505->dev;
-
-	DRM_DEV_DEBUG_DRIVER(dev, "video fifo overflow interrupt");
-	it6505->auto_train_retry = AUTO_TRAIN_RETRY;
-	flush_work(&it6505->link_works);
-	it6505_stop_hdcp(it6505);
-	it6505_video_reset(it6505);
+	return 1 & (addr[bit / BITS_PER_BYTE] >> (bit % BITS_PER_BYTE));
 }
 
-static void it6505_irq_io_latch_fifo_overflow(struct it6505 *it6505)
+static void it6505_irq_video_handler(struct it6505 *it6505, const int *int_status)
 {
 	struct device *dev = it6505->dev;
+	int reg_0d, reg_int03;
 
-	DRM_DEV_DEBUG_DRIVER(dev, "IO latch fifo overflow interrupt");
-	it6505->auto_train_retry = AUTO_TRAIN_RETRY;
-	flush_work(&it6505->link_works);
-	it6505_stop_hdcp(it6505);
-	it6505_video_reset(it6505);
-}
+	/*
+	 * When video SCDT change with video not stable,
+	 * Or video FIFO error, need video reset
+	 */
 
-static bool it6505_test_bit(unsigned int bit, const unsigned int *addr)
-{
-	return 1 & (addr[bit / BITS_PER_BYTE] >> (bit % BITS_PER_BYTE));
+	if ((!it6505_get_video_status(it6505) &&
+		(it6505_test_bit(INT_SCDT_CHANGE, (unsigned int *) int_status))) ||
+		(it6505_test_bit(BIT_INT_IO_FIFO_OVERFLOW, (unsigned int *) int_status)) ||
+		(it6505_test_bit(BIT_INT_VID_FIFO_ERROR, (unsigned int *) int_status))) {
+
+		it6505->auto_train_retry = AUTO_TRAIN_RETRY;
+		flush_work(&it6505->link_works);
+		it6505_stop_hdcp(it6505);
+		it6505_video_reset(it6505);
+
+		usleep_range(10000, 11000);
+
+		/*
+		 * Clear FIFO error IRQ to prevent fifo error -> reset loop
+		 * HW will trigger SCDT change IRQ again when video stable
+		 */
+
+		reg_int03 = it6505_read(it6505, INT_STATUS_03);
+		reg_0d = it6505_read(it6505, REG_SYSTEM_STS);
+
+		reg_int03 &= (BIT(INT_VID_FIFO_ERROR) | BIT(INT_IO_LATCH_FIFO_OVERFLOW));
+		it6505_write(it6505, INT_STATUS_03, reg_int03);
+
+		DRM_DEV_DEBUG_DRIVER(dev, "reg08 = 0x%02x", reg_int03);
+		DRM_DEV_DEBUG_DRIVER(dev, "reg0D = 0x%02x", reg_0d);
+
+		return;
+	}
+
+
+	if (it6505_test_bit(INT_SCDT_CHANGE, (unsigned int *) int_status))
+		it6505_irq_scdt(it6505);
 }
 
 static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
@@ -2508,15 +2535,12 @@  static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
 	} irq_vec[] = {
 		{ BIT_INT_HPD, it6505_irq_hpd },
 		{ BIT_INT_HPD_IRQ, it6505_irq_hpd_irq },
-		{ BIT_INT_SCDT, it6505_irq_scdt },
 		{ BIT_INT_HDCP_FAIL, it6505_irq_hdcp_fail },
 		{ BIT_INT_HDCP_DONE, it6505_irq_hdcp_done },
 		{ BIT_INT_AUX_CMD_FAIL, it6505_irq_aux_cmd_fail },
 		{ BIT_INT_HDCP_KSV_CHECK, it6505_irq_hdcp_ksv_check },
 		{ BIT_INT_AUDIO_FIFO_ERROR, it6505_irq_audio_fifo_error },
 		{ BIT_INT_LINK_TRAIN_FAIL, it6505_irq_link_train_fail },
-		{ BIT_INT_VID_FIFO_ERROR, it6505_irq_video_fifo_error },
-		{ BIT_INT_IO_FIFO_OVERFLOW, it6505_irq_io_latch_fifo_overflow },
 	};
 	int int_status[3], i;
 
@@ -2546,6 +2570,7 @@  static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
 			if (it6505_test_bit(irq_vec[i].bit, (unsigned int *)int_status))
 				irq_vec[i].handler(it6505);
 		}
+		it6505_irq_video_handler(it6505, (unsigned int *) int_status);
 	}
 
 	pm_runtime_put_sync(dev);