RE: [PATCH v7 1/1] drm/bridge: it6505: fix hibernate to resume no display issue

2024-05-14 Thread kuro.chung


-Original Message-
From: Kuro Chung (鐘仕廷) 
Sent: Tuesday, May 14, 2024 11:21 AM
To: 'Robert Foss' 
Cc: Allen Chen ; Pin-yen Lin ; 
Kenneth Hung (洪家倫) ; Kuro Chung 
; Andrzej Hajda 
; Neil Armstrong ; Laurent 
Pinchart ; Jonas Karlman ; 
Jernej Skrabec ; Maarten Lankhorst 
; Maxime Ripard ; Thomas 
Zimmermann ; David Airlie ; Daniel 
Vetter ; open list:DRM DRIVERS 
; open list 
Subject: RE: [PATCH v7 1/1] drm/bridge: it6505: fix hibernate to resume no 
display issue

-Original Message-
From: Robert Foss 
Sent: Tuesday, May 14, 2024 1:45 AM
To: Kuro Chung (鐘仕廷) 
Cc: Allen Chen ; Pin-yen Lin ; 
Kenneth Hung (洪家倫) ; Kuro Chung 
; Andrzej Hajda 
; Neil Armstrong ; Laurent 
Pinchart ; Jonas Karlman ; 
Jernej Skrabec ; Maarten Lankhorst 
; Maxime Ripard ; Thomas 
Zimmermann ; David Airlie ; Daniel 
Vetter ; open list:DRM DRIVERS 
; open list 
Subject: Re: [PATCH v7 1/1] drm/bridge: it6505: fix hibernate to resume no 
display issue

On Mon, May 13, 2024 at 7:42 PM Robert Foss  wrote:
>
> On Mon, May 6, 2024 at 11:36 AM kuro  wrote:
> >
> > From: Kuro 
> >
> > ITE 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.
> >
> > Signed-off-by: Kuro Chung 
> >
> > ---
> >  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 b53da9bb65a16..64e2706e3d0c3 100644
> > --- a/drivers/gpu/drm/bridge/ite-it6505.c
> > +++ b/drivers/gpu/drm/bridge/ite-it6505.c
> > @@ -1317,9 +1317,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); 
> > }
> >
> > @@ -2249,12 +2255,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) 
> > @@ -2475,31 +2480,53 @@ static void it6505_irq_link_train_fail(struct 
> > it6505 *it6505)
> > schedule_work(>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 = >client->dev;
> > -
> > -   DRM_DEV_DEBUG_DRIVER(dev, "video fifo overflow interrupt");
> > -   it6505->auto_train_retry = AUTO_TRAIN_RETRY;
> > -   flush_work(>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 = >client->dev;
> > +   int reg_0d, reg_int03;
> >
> > -   DRM_DEV

RE: [PATCH v7 1/1] drm/bridge: it6505: fix hibernate to resume no display issue

2024-05-13 Thread kuro.chung
-Original Message-
From: Robert Foss  
Sent: Tuesday, May 14, 2024 1:45 AM
To: Kuro Chung (鐘仕廷) 
Cc: Allen Chen ; Pin-yen Lin ; 
Kenneth Hung (洪家倫) ; Kuro Chung 
; Andrzej Hajda 
; Neil Armstrong ; Laurent 
Pinchart ; Jonas Karlman ; 
Jernej Skrabec ; Maarten Lankhorst 
; Maxime Ripard ; Thomas 
Zimmermann ; David Airlie ; Daniel 
Vetter ; open list:DRM DRIVERS 
; open list 
Subject: Re: [PATCH v7 1/1] drm/bridge: it6505: fix hibernate to resume no 
display issue

On Mon, May 13, 2024 at 7:42 PM Robert Foss  wrote:
>
> On Mon, May 6, 2024 at 11:36 AM kuro  wrote:
> >
> > From: Kuro 
> >
> > ITE 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.
> >
> > Signed-off-by: Kuro Chung 
> >
> > ---
> >  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 b53da9bb65a16..64e2706e3d0c3 100644
> > --- a/drivers/gpu/drm/bridge/ite-it6505.c
> > +++ b/drivers/gpu/drm/bridge/ite-it6505.c
> > @@ -1317,9 +1317,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);  
> > }
> >
> > @@ -2249,12 +2255,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) 
> > @@ -2475,31 +2480,53 @@ static void it6505_irq_link_train_fail(struct 
> > it6505 *it6505)
> > schedule_work(>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 = >client->dev;
> > -
> > -   DRM_DEV_DEBUG_DRIVER(dev, "video fifo overflow interrupt");
> > -   it6505->auto_train_retry = AUTO_TRAIN_RETRY;
> > -   flush_work(>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 = >client->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(>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
> > +*/
> >

Re: [PATCH v7 1/1] drm/bridge: it6505: fix hibernate to resume no display issue

2024-05-13 Thread Robert Foss
On Mon, May 13, 2024 at 7:42 PM Robert Foss  wrote:
>
> On Mon, May 6, 2024 at 11:36 AM kuro  wrote:
> >
> > From: Kuro 
> >
> > ITE 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.
> >
> > Signed-off-by: Kuro Chung 
> >
> > ---
> >  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 b53da9bb65a16..64e2706e3d0c3 100644
> > --- a/drivers/gpu/drm/bridge/ite-it6505.c
> > +++ b/drivers/gpu/drm/bridge/ite-it6505.c
> > @@ -1317,9 +1317,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);
> >  }
> >
> > @@ -2249,12 +2255,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)
> > @@ -2475,31 +2480,53 @@ static void it6505_irq_link_train_fail(struct 
> > it6505 *it6505)
> > schedule_work(>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 = >client->dev;
> > -
> > -   DRM_DEV_DEBUG_DRIVER(dev, "video fifo overflow interrupt");
> > -   it6505->auto_train_retry = AUTO_TRAIN_RETRY;
> > -   flush_work(>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 = >client->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(>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(>link_works);
> > +   it6505_stop_hdcp(it6505);
> > +   it6505_video_reset(it6505);
> > +
> > +   usleep_range(1, 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) | 
> > 

Re: [PATCH v7 1/1] drm/bridge: it6505: fix hibernate to resume no display issue

2024-05-13 Thread Robert Foss
On Mon, May 6, 2024 at 11:36 AM kuro  wrote:
>
> From: Kuro 
>
> ITE 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.
>
> Signed-off-by: Kuro Chung 
>
> ---
>  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 b53da9bb65a16..64e2706e3d0c3 100644
> --- a/drivers/gpu/drm/bridge/ite-it6505.c
> +++ b/drivers/gpu/drm/bridge/ite-it6505.c
> @@ -1317,9 +1317,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);
>  }
>
> @@ -2249,12 +2255,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)
> @@ -2475,31 +2480,53 @@ static void it6505_irq_link_train_fail(struct it6505 
> *it6505)
> schedule_work(>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 = >client->dev;
> -
> -   DRM_DEV_DEBUG_DRIVER(dev, "video fifo overflow interrupt");
> -   it6505->auto_train_retry = AUTO_TRAIN_RETRY;
> -   flush_work(>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 = >client->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(>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(>link_works);
> +   it6505_stop_hdcp(it6505);
> +   it6505_video_reset(it6505);
> +
> +   usleep_range(1, 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 

[PATCH v7 1/1] drm/bridge: it6505: fix hibernate to resume no display issue

2024-05-06 Thread kuro
From: Kuro 

ITE 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.

Signed-off-by: Kuro Chung 

---
 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 b53da9bb65a16..64e2706e3d0c3 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -1317,9 +1317,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);
 }
 
@@ -2249,12 +2255,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)
@@ -2475,31 +2480,53 @@ static void it6505_irq_link_train_fail(struct it6505 
*it6505)
schedule_work(>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 = >client->dev;
-
-   DRM_DEV_DEBUG_DRIVER(dev, "video fifo overflow interrupt");
-   it6505->auto_train_retry = AUTO_TRAIN_RETRY;
-   flush_work(>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 = >client->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(>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(>link_works);
+   it6505_stop_hdcp(it6505);
+   it6505_video_reset(it6505);
+
+   usleep_range(1, 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)
@@ -2512,15 +2539,12 @@ static irqreturn_t it6505_int_threaded_handler(int 
unused, void *data)
}