diff mbox series

Revert "drm/edid: Fix csync detailed mode parsing"

Message ID 20230815101907.2900768-1-jani.nikula@intel.com (mailing list archive)
State New, archived
Headers show
Series Revert "drm/edid: Fix csync detailed mode parsing" | expand

Commit Message

Jani Nikula Aug. 15, 2023, 10:19 a.m. UTC
This reverts commit ca62297b2085b5b3168bd891ca24862242c635a1.

Commit ca62297b2085 ("drm/edid: Fix csync detailed mode parsing") fixed
EDID detailed mode sync parsing. Unfortunately, there are quite a few
displays out there that have bogus (zero) sync field that are broken by
the change. Zero means analog composite sync, which is not right for
digital displays, and the modes get rejected. Regardless, it used to
work, and it needs to continue to work. Revert the change.

Rejecting modes with analog composite sync was the part that fixed the
gitlab issue 8146 [1]. We'll need to get back to the drawing board with
that.

[1] https://gitlab.freedesktop.org/drm/intel/-/issues/8146

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8789
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8930
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/9044
Fixes: ca62297b2085 ("drm/edid: Fix csync detailed mode parsing")
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v6.4+
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/drm_edid.c | 29 ++++++++---------------------
 include/drm/drm_edid.h     | 12 +++---------
 2 files changed, 11 insertions(+), 30 deletions(-)

Comments

Ville Syrjala Aug. 17, 2023, 11:35 a.m. UTC | #1
On Tue, Aug 15, 2023 at 01:19:07PM +0300, Jani Nikula wrote:
> This reverts commit ca62297b2085b5b3168bd891ca24862242c635a1.
> 
> Commit ca62297b2085 ("drm/edid: Fix csync detailed mode parsing") fixed
> EDID detailed mode sync parsing. Unfortunately, there are quite a few
> displays out there that have bogus (zero) sync field that are broken by
> the change. Zero means analog composite sync, which is not right for
> digital displays, and the modes get rejected. Regardless, it used to
> work, and it needs to continue to work. Revert the change.

Bah. I guess one option would be to quirk the bogus EDIDs, or maybe just
ignore bogus sync flags for the eDP preferred mode. But maybe needs a
bit more thinking, so

Acked-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> 
> Rejecting modes with analog composite sync was the part that fixed the
> gitlab issue 8146 [1]. We'll need to get back to the drawing board with
> that.
> 
> [1] https://gitlab.freedesktop.org/drm/intel/-/issues/8146
> 
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8789
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8930
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/9044
> Fixes: ca62297b2085 ("drm/edid: Fix csync detailed mode parsing")
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: dri-devel@lists.freedesktop.org
> Cc: <stable@vger.kernel.org> # v6.4+
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/drm_edid.c | 29 ++++++++---------------------
>  include/drm/drm_edid.h     | 12 +++---------
>  2 files changed, 11 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index f95152fac427..340da8257b51 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -3457,6 +3457,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
>  			    connector->base.id, connector->name);
>  		return NULL;
>  	}
> +	if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
> +		drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Composite sync not supported\n",
> +			    connector->base.id, connector->name);
> +	}
>  
>  	/* it is incorrect if hsync/vsync width is zero */
>  	if (!hsync_pulse_width || !vsync_pulse_width) {
> @@ -3503,27 +3507,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
>  	if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
>  		mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;
>  	} else {
> -		switch (pt->misc & DRM_EDID_PT_SYNC_MASK) {
> -		case DRM_EDID_PT_ANALOG_CSYNC:
> -		case DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC:
> -			drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Analog composite sync!\n",
> -				    connector->base.id, connector->name);
> -			mode->flags |= DRM_MODE_FLAG_CSYNC | DRM_MODE_FLAG_NCSYNC;
> -			break;
> -		case DRM_EDID_PT_DIGITAL_CSYNC:
> -			drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Digital composite sync!\n",
> -				    connector->base.id, connector->name);
> -			mode->flags |= DRM_MODE_FLAG_CSYNC;
> -			mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
> -				DRM_MODE_FLAG_PCSYNC : DRM_MODE_FLAG_NCSYNC;
> -			break;
> -		case DRM_EDID_PT_DIGITAL_SEPARATE_SYNC:
> -			mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
> -				DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
> -			mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
> -				DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
> -			break;
> -		}
> +		mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
> +			DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
> +		mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
> +			DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
>  	}
>  
>  set_size:
> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> index 169755d3de19..48e93f909ef6 100644
> --- a/include/drm/drm_edid.h
> +++ b/include/drm/drm_edid.h
> @@ -61,15 +61,9 @@ struct std_timing {
>  	u8 vfreq_aspect;
>  } __attribute__((packed));
>  
> -#define DRM_EDID_PT_SYNC_MASK              (3 << 3)
> -# define DRM_EDID_PT_ANALOG_CSYNC          (0 << 3)
> -# define DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC  (1 << 3)
> -# define DRM_EDID_PT_DIGITAL_CSYNC         (2 << 3)
> -#  define DRM_EDID_PT_CSYNC_ON_RGB         (1 << 1) /* analog csync only */
> -#  define DRM_EDID_PT_CSYNC_SERRATE        (1 << 2)
> -# define DRM_EDID_PT_DIGITAL_SEPARATE_SYNC (3 << 3)
> -#  define DRM_EDID_PT_HSYNC_POSITIVE       (1 << 1) /* also digital csync */
> -#  define DRM_EDID_PT_VSYNC_POSITIVE       (1 << 2)
> +#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1)
> +#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2)
> +#define DRM_EDID_PT_SEPARATE_SYNC  (3 << 3)
>  #define DRM_EDID_PT_STEREO         (1 << 5)
>  #define DRM_EDID_PT_INTERLACED     (1 << 7)
>  
> -- 
> 2.39.2
Jani Nikula Aug. 17, 2023, 12:40 p.m. UTC | #2
On Thu, 17 Aug 2023, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> On Tue, Aug 15, 2023 at 01:19:07PM +0300, Jani Nikula wrote:
>> This reverts commit ca62297b2085b5b3168bd891ca24862242c635a1.
>> 
>> Commit ca62297b2085 ("drm/edid: Fix csync detailed mode parsing") fixed
>> EDID detailed mode sync parsing. Unfortunately, there are quite a few
>> displays out there that have bogus (zero) sync field that are broken by
>> the change. Zero means analog composite sync, which is not right for
>> digital displays, and the modes get rejected. Regardless, it used to
>> work, and it needs to continue to work. Revert the change.
>
> Bah. I guess one option would be to quirk the bogus EDIDs, or maybe just
> ignore bogus sync flags for the eDP preferred mode. But maybe needs a
> bit more thinking, so
>
> Acked-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Thanks, pushed to drm-misc-fixes.

BR,
Jani.


>
>> 
>> Rejecting modes with analog composite sync was the part that fixed the
>> gitlab issue 8146 [1]. We'll need to get back to the drawing board with
>> that.
>> 
>> [1] https://gitlab.freedesktop.org/drm/intel/-/issues/8146
>> 
>> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8789
>> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8930
>> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/9044
>> Fixes: ca62297b2085 ("drm/edid: Fix csync detailed mode parsing")
>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Cc: dri-devel@lists.freedesktop.org
>> Cc: <stable@vger.kernel.org> # v6.4+
>> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
>> ---
>>  drivers/gpu/drm/drm_edid.c | 29 ++++++++---------------------
>>  include/drm/drm_edid.h     | 12 +++---------
>>  2 files changed, 11 insertions(+), 30 deletions(-)
>> 
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index f95152fac427..340da8257b51 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -3457,6 +3457,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
>>  			    connector->base.id, connector->name);
>>  		return NULL;
>>  	}
>> +	if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
>> +		drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Composite sync not supported\n",
>> +			    connector->base.id, connector->name);
>> +	}
>>  
>>  	/* it is incorrect if hsync/vsync width is zero */
>>  	if (!hsync_pulse_width || !vsync_pulse_width) {
>> @@ -3503,27 +3507,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
>>  	if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
>>  		mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;
>>  	} else {
>> -		switch (pt->misc & DRM_EDID_PT_SYNC_MASK) {
>> -		case DRM_EDID_PT_ANALOG_CSYNC:
>> -		case DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC:
>> -			drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Analog composite sync!\n",
>> -				    connector->base.id, connector->name);
>> -			mode->flags |= DRM_MODE_FLAG_CSYNC | DRM_MODE_FLAG_NCSYNC;
>> -			break;
>> -		case DRM_EDID_PT_DIGITAL_CSYNC:
>> -			drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Digital composite sync!\n",
>> -				    connector->base.id, connector->name);
>> -			mode->flags |= DRM_MODE_FLAG_CSYNC;
>> -			mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
>> -				DRM_MODE_FLAG_PCSYNC : DRM_MODE_FLAG_NCSYNC;
>> -			break;
>> -		case DRM_EDID_PT_DIGITAL_SEPARATE_SYNC:
>> -			mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
>> -				DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
>> -			mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
>> -				DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
>> -			break;
>> -		}
>> +		mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
>> +			DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
>> +		mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
>> +			DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
>>  	}
>>  
>>  set_size:
>> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
>> index 169755d3de19..48e93f909ef6 100644
>> --- a/include/drm/drm_edid.h
>> +++ b/include/drm/drm_edid.h
>> @@ -61,15 +61,9 @@ struct std_timing {
>>  	u8 vfreq_aspect;
>>  } __attribute__((packed));
>>  
>> -#define DRM_EDID_PT_SYNC_MASK              (3 << 3)
>> -# define DRM_EDID_PT_ANALOG_CSYNC          (0 << 3)
>> -# define DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC  (1 << 3)
>> -# define DRM_EDID_PT_DIGITAL_CSYNC         (2 << 3)
>> -#  define DRM_EDID_PT_CSYNC_ON_RGB         (1 << 1) /* analog csync only */
>> -#  define DRM_EDID_PT_CSYNC_SERRATE        (1 << 2)
>> -# define DRM_EDID_PT_DIGITAL_SEPARATE_SYNC (3 << 3)
>> -#  define DRM_EDID_PT_HSYNC_POSITIVE       (1 << 1) /* also digital csync */
>> -#  define DRM_EDID_PT_VSYNC_POSITIVE       (1 << 2)
>> +#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1)
>> +#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2)
>> +#define DRM_EDID_PT_SEPARATE_SYNC  (3 << 3)
>>  #define DRM_EDID_PT_STEREO         (1 << 5)
>>  #define DRM_EDID_PT_INTERLACED     (1 << 7)
>>  
>> -- 
>> 2.39.2
Jani Nikula Aug. 17, 2023, 1:05 p.m. UTC | #3
On Thu, 17 Aug 2023, Dirk Lehmann <develop@dj-l.de> wrote:
> VESA Enhanced EDID Standard does not clearly describe how display
> panel vendors should setup the Sync Signal Defintions (bit 4 & 3) in
> the Detailed Timing Definition (relative offset 17, absolute offset
> 47h[+18]) for Digital Video Signal Interfaces (bit 7 at offset 14h).
>
> In practice many eDP panels which using a Digital Video Signal
> Interfaces (bit 7 at offset 14h == 1) are leaving the Sync Signal
> Defintions at offset 47h[+18] blank 0x00, which would mean concerned
> with the VESA Standard [1] that they are using "Analog Composite
> Sync".
>
> Fix: Just detect Analog Sync Signal if an Analog Video Signal
>      Interface (bit 7 at offset 14h == 0) is in use.  Just detect
>      Digital Sync Signal if an Digital Video Signal Interface is in
>      use.
>
> Reference: [1] VESA Enhanced EDID Standard, Release A, Rev.2, Page 35

Please don't reply with patches in-reply-to other people's patches.

> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8789

This is now fixed by the revert that I just pushed.

> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8146

I don't think this patch fixes that one; see below.

> Signed-off-by: Dirk Lehmann <develop@dj-l.de>
> ---
>  drivers/gpu/drm/drm_edid.c | 74 ++++++++++++++++++++++++++++++++------
>  include/drm/drm_edid.h     | 12 +++++--
>  2 files changed, 73 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 1f470968ed14..6afdc34e55ce 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -3437,6 +3437,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
>  	const struct drm_display_info *info = &connector->display_info;
>  	struct drm_device *dev = connector->dev;
>  	struct drm_display_mode *mode;
> +	const struct edid *edid = drm_edid->edid;
>  	const struct detailed_pixel_timing *pt = &timing->data.pixel_data;
>  	unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo;
>  	unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo;
> @@ -3456,10 +3457,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
>  			    connector->base.id, connector->name);
>  		return NULL;
>  	}
> -	if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
> -		drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Composite sync not supported\n",
> -			    connector->base.id, connector->name);
> -	}
>  
>  	/* it is incorrect if hsync/vsync width is zero */
>  	if (!hsync_pulse_width || !vsync_pulse_width) {
> @@ -3505,11 +3502,68 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
>  
>  	if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
>  		mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;
> +	} else if (edid->input & DRM_EDID_INPUT_DIGITAL) {
> +		/* !info->quirks && edid->input == DIGITAL  */
> +		switch (pt->misc & DRM_EDID_PT_SYNC_MASK) {
> +		/* VESA Enhanced EDID Standard, Release A, Rev.2, Page 35
> +		 *
> +		 * CASE DRM_EDID_PT_ANALOG_CSYNC:
> +		 *
> +		 * (pt->misc & DRM_EDID_PT_SYNC_MASK == 0x00) means
> +		 * "Analog Composite Sync" as described in VESA
> +		 * Standard.  But many digital display panels without
> +		 * composite sync are also using 0x00 here.
> +		 *
> +		 * Therefore use DEFAULT: as we are currently on an
> +		 * digital video signal interface.
> +		 */
> +		case DRM_EDID_PT_DIGITAL_CSYNC:
> +			drm_dbg_kms(dev,
> +				"[CONNECTOR:%d:%s] Digital composite sync!\n",
> +				connector->base.id, connector->name);
> +			mode->flags |= DRM_MODE_FLAG_CSYNC;
> +			mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
> +				DRM_MODE_FLAG_PCSYNC : DRM_MODE_FLAG_NCSYNC;
> +			break;
> +		case DRM_EDID_PT_DIGITAL_SEPARATE_SYNC:
> +			drm_dbg_kms(dev,
> +				"[CONNECTOR:%d:%s] Digital seperate sync!\n",
> +				connector->base.id, connector->name);
> +			goto digital_default;
> +			break; /* Missing BREAK throws a compiler warning  */

fallthrough; will do the trick.

> +		default:
> +digital_default:
> +			mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
> +				DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
> +			mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
> +				DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;

The failing mode in bug [1] has 0x0a for flags, so it ends up here, and
for that display this patch is a no-op.

As I explained in [2], all the problematic cases have invalid data, but
the ones fixed by the revert need to ignore the analog sync *flags* and
accept the mode, and the display in [1] needs to have the whole *mode*
rejected.

[1] https://gitlab.freedesktop.org/drm/intel/-/issues/8146
[2] https://gitlab.freedesktop.org/drm/intel/-/issues/8789#note_2047902

> +			break;
> +		}
>  	} else {
> -		mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
> -			DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
> -		mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
> -			DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
> +		/* !info->quirks && edid->input == ANALOG  */
> +		switch (pt->misc & DRM_EDID_PT_SYNC_MASK) {
> +		/* VESA Enhanced EDID Standard, Release A, Rev.2, Page 35
> +		 *
> +		 * CASE DRM_EDID_PT_ANALOG_CSYNC:
> +		 *
> +		 * (pt->misc & DRM_EDID_PT_SYNC_MASK == 0x00) for
> +		 * "Analog Composite Sync" is possible here, as we are
> +		 * currently on an analog video signal interface.
> +		 */
> +		case DRM_EDID_PT_ANALOG_CSYNC:
> +		case DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC:
> +			drm_dbg_kms(dev,
> +				"[CONNECTOR:%d:%s] Analog composite sync!\n",
> +				connector->base.id, connector->name);
> +			mode->flags |= DRM_MODE_FLAG_CSYNC | DRM_MODE_FLAG_NCSYNC;
> +			break;
> +		default:
> +			mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
> +				DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
> +			mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
> +				DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
> +			break;
> +		}

Another angle is that for analog displays, EDID offset 0x14 has info
about the supported sync modes. If we're separating digital/analog sync
handling, we should probably filter the analog sync with the info from
0x14.

BR,
Jani.


>  	}
>  
>  set_size:
> @@ -3522,8 +3576,8 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
>  	}
>  
>  	if (info->quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
> -		mode->width_mm = drm_edid->edid->width_cm * 10;
> -		mode->height_mm = drm_edid->edid->height_cm * 10;
> +		mode->width_mm = edid->width_cm * 10;
> +		mode->height_mm = edid->height_cm * 10;
>  	}
>  
>  	mode->type = DRM_MODE_TYPE_DRIVER;
> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> index 48e93f909ef6..169755d3de19 100644
> --- a/include/drm/drm_edid.h
> +++ b/include/drm/drm_edid.h
> @@ -61,9 +61,15 @@ struct std_timing {
>  	u8 vfreq_aspect;
>  } __attribute__((packed));
>  
> -#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1)
> -#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2)
> -#define DRM_EDID_PT_SEPARATE_SYNC  (3 << 3)
> +#define DRM_EDID_PT_SYNC_MASK              (3 << 3)
> +# define DRM_EDID_PT_ANALOG_CSYNC          (0 << 3)
> +# define DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC  (1 << 3)
> +# define DRM_EDID_PT_DIGITAL_CSYNC         (2 << 3)
> +#  define DRM_EDID_PT_CSYNC_ON_RGB         (1 << 1) /* analog csync only */
> +#  define DRM_EDID_PT_CSYNC_SERRATE        (1 << 2)
> +# define DRM_EDID_PT_DIGITAL_SEPARATE_SYNC (3 << 3)
> +#  define DRM_EDID_PT_HSYNC_POSITIVE       (1 << 1) /* also digital csync */
> +#  define DRM_EDID_PT_VSYNC_POSITIVE       (1 << 2)
>  #define DRM_EDID_PT_STEREO         (1 << 5)
>  #define DRM_EDID_PT_INTERLACED     (1 << 7)
Dirk Lehmann Aug. 17, 2023, 2:29 p.m. UTC | #4
Hey Jani,

On 8/17/23 15:05, Jani Nikula wrote:
> On Thu, 17 Aug 2023, Dirk Lehmann <develop@dj-l.de> wrote:
>> VESA Enhanced EDID Standard does not clearly describe how display
>> panel vendors should setup the Sync Signal Defintions (bit 4 & 3) in
>> the Detailed Timing Definition (relative offset 17, absolute offset
>> 47h[+18]) for Digital Video Signal Interfaces (bit 7 at offset 14h).
>>
>> In practice many eDP panels which using a Digital Video Signal
>> Interfaces (bit 7 at offset 14h == 1) are leaving the Sync Signal
>> Defintions at offset 47h[+18] blank 0x00, which would mean concerned
>> with the VESA Standard [1] that they are using "Analog Composite
>> Sync".
>>
>> Fix: Just detect Analog Sync Signal if an Analog Video Signal
>>       Interface (bit 7 at offset 14h == 0) is in use.  Just detect
>>       Digital Sync Signal if an Digital Video Signal Interface is in
>>       use.
>>
>> Reference: [1] VESA Enhanced EDID Standard, Release A, Rev.2, Page 35
> 
> Please don't reply with patches in-reply-to other people's patches.

Sorry, I am new with such patch lists :/ ...

> 
>> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8789
> 
> This is now fixed by the revert that I just pushed.
> 
>> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8146
> 
> I don't think this patch fixes that one; see below.
> 
>> Signed-off-by: Dirk Lehmann <develop@dj-l.de>
>> ---
>>   drivers/gpu/drm/drm_edid.c | 74 ++++++++++++++++++++++++++++++++------
>>   include/drm/drm_edid.h     | 12 +++++--
>>   2 files changed, 73 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index 1f470968ed14..6afdc34e55ce 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -3437,6 +3437,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
>>   	const struct drm_display_info *info = &connector->display_info;
>>   	struct drm_device *dev = connector->dev;
>>   	struct drm_display_mode *mode;
>> +	const struct edid *edid = drm_edid->edid;
>>   	const struct detailed_pixel_timing *pt = &timing->data.pixel_data;
>>   	unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo;
>>   	unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo;
>> @@ -3456,10 +3457,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
>>   			    connector->base.id, connector->name);
>>   		return NULL;
>>   	}
>> -	if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
>> -		drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Composite sync not supported\n",
>> -			    connector->base.id, connector->name);
>> -	}
>>   
>>   	/* it is incorrect if hsync/vsync width is zero */
>>   	if (!hsync_pulse_width || !vsync_pulse_width) {
>> @@ -3505,11 +3502,68 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
>>   
>>   	if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
>>   		mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;
>> +	} else if (edid->input & DRM_EDID_INPUT_DIGITAL) {
>> +		/* !info->quirks && edid->input == DIGITAL  */
>> +		switch (pt->misc & DRM_EDID_PT_SYNC_MASK) {
>> +		/* VESA Enhanced EDID Standard, Release A, Rev.2, Page 35
>> +		 *
>> +		 * CASE DRM_EDID_PT_ANALOG_CSYNC:
>> +		 *
>> +		 * (pt->misc & DRM_EDID_PT_SYNC_MASK == 0x00) means
>> +		 * "Analog Composite Sync" as described in VESA
>> +		 * Standard.  But many digital display panels without
>> +		 * composite sync are also using 0x00 here.
>> +		 *
>> +		 * Therefore use DEFAULT: as we are currently on an
>> +		 * digital video signal interface.
>> +		 */
>> +		case DRM_EDID_PT_DIGITAL_CSYNC:
>> +			drm_dbg_kms(dev,
>> +				"[CONNECTOR:%d:%s] Digital composite sync!\n",
>> +				connector->base.id, connector->name);
>> +			mode->flags |= DRM_MODE_FLAG_CSYNC;
>> +			mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
>> +				DRM_MODE_FLAG_PCSYNC : DRM_MODE_FLAG_NCSYNC;
>> +			break;
>> +		case DRM_EDID_PT_DIGITAL_SEPARATE_SYNC:
>> +			drm_dbg_kms(dev,
>> +				"[CONNECTOR:%d:%s] Digital seperate sync!\n",
>> +				connector->base.id, connector->name);
>> +			goto digital_default;
>> +			break; /* Missing BREAK throws a compiler warning  */
> 
> fallthrough; will do the trick.

Cool, that's new for me.  FALLTHROUGH really works, great :)

> 
>> +		default:
>> +digital_default:
>> +			mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
>> +				DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
>> +			mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
>> +				DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
> 
> The failing mode in bug [1] has 0x0a for flags, so it ends up here, and
> for that display this patch is a no-op.

Aaaeem yes, something is wrong here.  If the EDID data are correct, then 
since 0001-*_5.15.patch in [1] should broke the implementation.

   (0x1a & (3 << 3)) == (3 << 3) == DRM_EDID_PT_DIGITAL_SEPARATE_SYNC

But this implementation here I made and we are discussing should be have 
the same behavior as before in that case of [1].  The no-op should also 
be before.  But then the fix ca62297b2085b before is useless.  Yes, you 
are right, then reverting is the better idea xD

> 
> As I explained in [2], all the problematic cases have invalid data, but
> the ones fixed by the revert need to ignore the analog sync *flags* and
> accept the mode, and the display in [1] needs to have the whole *mode*
> rejected.
> 

I don't know about the other problematic cases.  I don't have the data 
of the use cases for that.

> [1] https://gitlab.freedesktop.org/drm/intel/-/issues/8146
> [2] https://gitlab.freedesktop.org/drm/intel/-/issues/8789#note_2047902
> 
>> +			break;
>> +		}
>>   	} else {
>> -		mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
>> -			DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
>> -		mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
>> -			DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
>> +		/* !info->quirks && edid->input == ANALOG  */
>> +		switch (pt->misc & DRM_EDID_PT_SYNC_MASK) {
>> +		/* VESA Enhanced EDID Standard, Release A, Rev.2, Page 35
>> +		 *
>> +		 * CASE DRM_EDID_PT_ANALOG_CSYNC:
>> +		 *
>> +		 * (pt->misc & DRM_EDID_PT_SYNC_MASK == 0x00) for
>> +		 * "Analog Composite Sync" is possible here, as we are
>> +		 * currently on an analog video signal interface.
>> +		 */
>> +		case DRM_EDID_PT_ANALOG_CSYNC:
>> +		case DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC:
>> +			drm_dbg_kms(dev,
>> +				"[CONNECTOR:%d:%s] Analog composite sync!\n",
>> +				connector->base.id, connector->name);
>> +			mode->flags |= DRM_MODE_FLAG_CSYNC | DRM_MODE_FLAG_NCSYNC;
>> +			break;
>> +		default:
>> +			mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
>> +				DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
>> +			mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
>> +				DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
>> +			break;
>> +		}
> 
> Another angle is that for analog displays, EDID offset 0x14 has info
> about the supported sync modes. If we're separating digital/analog sync
> handling, we should probably filter the analog sync with the info from
> 0x14.

Yeah I also saw that in the VESA Standard, but I reflected that the 
analog display implementation should be more stable, as they are longer 
exist.  For current digital eDP panels which have 0x00 at 47h are these 
composite bits at 14h not reachable --- because bit 7 of 14h is 1.  It 
may just have effects on older analog displays.

> 
> BR,
> Jani.
> 

Okay, summary: You may be right, as the fix commit ca62297b2085b makes 
less sense.

Yeah, greets and thanks for the fast fix.  Really great =D
Dirk

> 
>>   	}
>>   
>>   set_size:
>> @@ -3522,8 +3576,8 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
>>   	}
>>   
>>   	if (info->quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
>> -		mode->width_mm = drm_edid->edid->width_cm * 10;
>> -		mode->height_mm = drm_edid->edid->height_cm * 10;
>> +		mode->width_mm = edid->width_cm * 10;
>> +		mode->height_mm = edid->height_cm * 10;
>>   	}
>>   
>>   	mode->type = DRM_MODE_TYPE_DRIVER;
>> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
>> index 48e93f909ef6..169755d3de19 100644
>> --- a/include/drm/drm_edid.h
>> +++ b/include/drm/drm_edid.h
>> @@ -61,9 +61,15 @@ struct std_timing {
>>   	u8 vfreq_aspect;
>>   } __attribute__((packed));
>>   
>> -#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1)
>> -#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2)
>> -#define DRM_EDID_PT_SEPARATE_SYNC  (3 << 3)
>> +#define DRM_EDID_PT_SYNC_MASK              (3 << 3)
>> +# define DRM_EDID_PT_ANALOG_CSYNC          (0 << 3)
>> +# define DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC  (1 << 3)
>> +# define DRM_EDID_PT_DIGITAL_CSYNC         (2 << 3)
>> +#  define DRM_EDID_PT_CSYNC_ON_RGB         (1 << 1) /* analog csync only */
>> +#  define DRM_EDID_PT_CSYNC_SERRATE        (1 << 2)
>> +# define DRM_EDID_PT_DIGITAL_SEPARATE_SYNC (3 << 3)
>> +#  define DRM_EDID_PT_HSYNC_POSITIVE       (1 << 1) /* also digital csync */
>> +#  define DRM_EDID_PT_VSYNC_POSITIVE       (1 << 2)
>>   #define DRM_EDID_PT_STEREO         (1 << 5)
>>   #define DRM_EDID_PT_INTERLACED     (1 << 7)
>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index f95152fac427..340da8257b51 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3457,6 +3457,10 @@  static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
 			    connector->base.id, connector->name);
 		return NULL;
 	}
+	if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
+		drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Composite sync not supported\n",
+			    connector->base.id, connector->name);
+	}
 
 	/* it is incorrect if hsync/vsync width is zero */
 	if (!hsync_pulse_width || !vsync_pulse_width) {
@@ -3503,27 +3507,10 @@  static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
 	if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
 		mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;
 	} else {
-		switch (pt->misc & DRM_EDID_PT_SYNC_MASK) {
-		case DRM_EDID_PT_ANALOG_CSYNC:
-		case DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC:
-			drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Analog composite sync!\n",
-				    connector->base.id, connector->name);
-			mode->flags |= DRM_MODE_FLAG_CSYNC | DRM_MODE_FLAG_NCSYNC;
-			break;
-		case DRM_EDID_PT_DIGITAL_CSYNC:
-			drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Digital composite sync!\n",
-				    connector->base.id, connector->name);
-			mode->flags |= DRM_MODE_FLAG_CSYNC;
-			mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
-				DRM_MODE_FLAG_PCSYNC : DRM_MODE_FLAG_NCSYNC;
-			break;
-		case DRM_EDID_PT_DIGITAL_SEPARATE_SYNC:
-			mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
-				DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
-			mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
-				DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
-			break;
-		}
+		mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
+			DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
+		mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
+			DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
 	}
 
 set_size:
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 169755d3de19..48e93f909ef6 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -61,15 +61,9 @@  struct std_timing {
 	u8 vfreq_aspect;
 } __attribute__((packed));
 
-#define DRM_EDID_PT_SYNC_MASK              (3 << 3)
-# define DRM_EDID_PT_ANALOG_CSYNC          (0 << 3)
-# define DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC  (1 << 3)
-# define DRM_EDID_PT_DIGITAL_CSYNC         (2 << 3)
-#  define DRM_EDID_PT_CSYNC_ON_RGB         (1 << 1) /* analog csync only */
-#  define DRM_EDID_PT_CSYNC_SERRATE        (1 << 2)
-# define DRM_EDID_PT_DIGITAL_SEPARATE_SYNC (3 << 3)
-#  define DRM_EDID_PT_HSYNC_POSITIVE       (1 << 1) /* also digital csync */
-#  define DRM_EDID_PT_VSYNC_POSITIVE       (1 << 2)
+#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1)
+#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2)
+#define DRM_EDID_PT_SEPARATE_SYNC  (3 << 3)
 #define DRM_EDID_PT_STEREO         (1 << 5)
 #define DRM_EDID_PT_INTERLACED     (1 << 7)