Commit 7fa846b9 authored by Dom Cobley's avatar Dom Cobley Committed by Maxime Ripard

drm/vc4: hdmi: Always enable GCP with AVMUTE cleared

Issue is some displays go blank at the point of firmware to kms
handover.  Plugging/unplugging hdmi cable, power cycling display, or
switching standby off/on
typically resolve this case.

Finally managed to find a display that suffers from this, and track down
the issue.

The firmware uses AVMUTE in normal operation. It will set AVMUTE before
disabling hdmi clocks and phy. It will clear AVMUTE after clocks and phy
are set up for a new hdmi mode.

But with the hdmi handover from firmware to kms, AVMUTE will be set by
firmware.

kms driver typically has no GCP packet (except for deep colour modes).
The spec isn't clear on whether to consider the AVMUTE as continuing
indefinitely in the absence of a GCP packet, or to consider that state
to have ended.

Most displays behave as we want, but there are a number (from multiple
manufacturers) which need to see AVMUTE cleared before displaying a
picture.

Lets just always enable GCP packet with AVMUTE cleared. That resolves
the issue on problematic displays.

From HDMI 1.4 spec:

  A CD field of zero (Color Depth not indicated) shall be used whenever
  the Sink does not indicate support for Deep Color. This value may
  also be used in Deep Color mode to transmit a GCP indicating only
  non-Deep Color information (e.g. AVMUTE).

So use CD=0 where we were previously not enabling a GCP.

Link: https://forum.libreelec.tv/thread/24780-le-10-0-1-rpi4-no-picture-after-update-from-le-10-0-0Signed-off-by: default avatarDom Cobley <popcornmix@gmail.com>
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20230127161219.457058-1-maxime@cerno.tech
parent 6b77b16d
...@@ -97,6 +97,10 @@ ...@@ -97,6 +97,10 @@
#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_SHIFT 8 #define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_SHIFT 8
#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK VC4_MASK(15, 8) #define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK VC4_MASK(15, 8)
#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_0_MASK VC4_MASK(7, 0)
#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_0_SET_AVMUTE BIT(0)
#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_0_CLEAR_AVMUTE BIT(4)
# define VC4_HD_M_SW_RST BIT(2) # define VC4_HD_M_SW_RST BIT(2)
# define VC4_HD_M_ENABLE BIT(0) # define VC4_HD_M_ENABLE BIT(0)
...@@ -1306,7 +1310,6 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, ...@@ -1306,7 +1310,6 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
VC4_HDMI_VERTB_VBP)); VC4_HDMI_VERTB_VBP));
unsigned long flags; unsigned long flags;
unsigned char gcp; unsigned char gcp;
bool gcp_en;
u32 reg; u32 reg;
int idx; int idx;
...@@ -1341,16 +1344,13 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, ...@@ -1341,16 +1344,13 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
switch (vc4_state->output_bpc) { switch (vc4_state->output_bpc) {
case 12: case 12:
gcp = 6; gcp = 6;
gcp_en = true;
break; break;
case 10: case 10:
gcp = 5; gcp = 5;
gcp_en = true;
break; break;
case 8: case 8:
default: default:
gcp = 4; gcp = 0;
gcp_en = false;
break; break;
} }
...@@ -1359,8 +1359,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, ...@@ -1359,8 +1359,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
* doesn't signal in GCP. * doesn't signal in GCP.
*/ */
if (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) { if (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) {
gcp = 4; gcp = 0;
gcp_en = false;
} }
reg = HDMI_READ(HDMI_DEEP_COLOR_CONFIG_1); reg = HDMI_READ(HDMI_DEEP_COLOR_CONFIG_1);
...@@ -1373,11 +1372,12 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, ...@@ -1373,11 +1372,12 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
reg = HDMI_READ(HDMI_GCP_WORD_1); reg = HDMI_READ(HDMI_GCP_WORD_1);
reg &= ~VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK; reg &= ~VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK;
reg |= VC4_SET_FIELD(gcp, VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1); reg |= VC4_SET_FIELD(gcp, VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1);
reg &= ~VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_0_MASK;
reg |= VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_0_CLEAR_AVMUTE;
HDMI_WRITE(HDMI_GCP_WORD_1, reg); HDMI_WRITE(HDMI_GCP_WORD_1, reg);
reg = HDMI_READ(HDMI_GCP_CONFIG); reg = HDMI_READ(HDMI_GCP_CONFIG);
reg &= ~VC5_HDMI_GCP_CONFIG_GCP_ENABLE; reg |= VC5_HDMI_GCP_CONFIG_GCP_ENABLE;
reg |= gcp_en ? VC5_HDMI_GCP_CONFIG_GCP_ENABLE : 0;
HDMI_WRITE(HDMI_GCP_CONFIG, reg); HDMI_WRITE(HDMI_GCP_CONFIG, reg);
reg = HDMI_READ(HDMI_MISC_CONTROL); reg = HDMI_READ(HDMI_MISC_CONTROL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment