On Tue, Oct 28, 2025 at 5:26 PM Jani Nikula <[email protected]> wrote:
>
> Add a mechanism for DisplayID specific quirks, and add the first quirk
> to ignore DisplayID section checksum errors.
>
> It would be quite inconvenient to pass existing EDID quirks from
> drm_edid.c for DisplayID parsing. Not all places doing DisplayID
> iteration have the quirks readily available, and would have to pass it
> in all places. Simply add a separate array of DisplayID specific EDID
> quirks. We do end up checking it every time we iterate DisplayID blocks,
> but hopefully the number of quirks remains small.
>
> There are a few laptop models with DisplayID checksum failures, leading
> to higher refresh rates only present in the DisplayID blocks being
> ignored. Add a quirk for the panel in the machines.
>
> Reported-by: Tiago Martins Araújo <[email protected]>
> Closes: 
> https://lore.kernel.org/r/cacrbrpgvlp5lanxufi6z0s7xmbag4x5y2yolbdxfovtfggq...@mail.gmail.com
> Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14703
> Signed-off-by: Jani Nikula <[email protected]>

Series is:
Acked-by: Alex Deucher <[email protected]>

> ---
>  drivers/gpu/drm/drm_displayid.c          | 41 +++++++++++++++++++++---
>  drivers/gpu/drm/drm_displayid_internal.h |  2 ++
>  2 files changed, 39 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_displayid.c b/drivers/gpu/drm/drm_displayid.c
> index 20b453d2b854..58d0bb6d2676 100644
> --- a/drivers/gpu/drm/drm_displayid.c
> +++ b/drivers/gpu/drm/drm_displayid.c
> @@ -9,6 +9,34 @@
>  #include "drm_crtc_internal.h"
>  #include "drm_displayid_internal.h"
>
> +enum {
> +       QUIRK_IGNORE_CHECKSUM,
> +};
> +
> +struct displayid_quirk {
> +       const struct drm_edid_ident ident;
> +       u8 quirks;
> +};
> +
> +static const struct displayid_quirk quirks[] = {
> +       {
> +               .ident = DRM_EDID_IDENT_INIT('C', 'S', 'O', 5142, 
> "MNE007ZA1-5"),
> +               .quirks = BIT(QUIRK_IGNORE_CHECKSUM),
> +       },
> +};
> +
> +static u8 get_quirks(const struct drm_edid *drm_edid)
> +{
> +       int i;
> +
> +       for (i = 0; i < ARRAY_SIZE(quirks); i++) {
> +               if (drm_edid_match(drm_edid, &quirks[i].ident))
> +                       return quirks[i].quirks;
> +       }
> +
> +       return 0;
> +}
> +
>  static const struct displayid_header *
>  displayid_get_header(const u8 *displayid, int length, int index)
>  {
> @@ -23,7 +51,7 @@ displayid_get_header(const u8 *displayid, int length, int 
> index)
>  }
>
>  static const struct displayid_header *
> -validate_displayid(const u8 *displayid, int length, int idx)
> +validate_displayid(const u8 *displayid, int length, int idx, bool 
> ignore_checksum)
>  {
>         int i, dispid_length;
>         u8 csum = 0;
> @@ -41,8 +69,11 @@ validate_displayid(const u8 *displayid, int length, int 
> idx)
>         for (i = 0; i < dispid_length; i++)
>                 csum += displayid[idx + i];
>         if (csum) {
> -               DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", 
> csum);
> -               return ERR_PTR(-EINVAL);
> +               DRM_NOTE("DisplayID checksum invalid, remainder is %d%s\n", 
> csum,
> +                        ignore_checksum ? " (ignoring)" : "");
> +
> +               if (!ignore_checksum)
> +                       return ERR_PTR(-EINVAL);
>         }
>
>         return base;
> @@ -52,6 +83,7 @@ static const u8 *find_next_displayid_extension(struct 
> displayid_iter *iter)
>  {
>         const struct displayid_header *base;
>         const u8 *displayid;
> +       bool ignore_checksum = iter->quirks & BIT(QUIRK_IGNORE_CHECKSUM);
>
>         displayid = drm_edid_find_extension(iter->drm_edid, DISPLAYID_EXT, 
> &iter->ext_index);
>         if (!displayid)
> @@ -61,7 +93,7 @@ static const u8 *find_next_displayid_extension(struct 
> displayid_iter *iter)
>         iter->length = EDID_LENGTH - 1;
>         iter->idx = 1;
>
> -       base = validate_displayid(displayid, iter->length, iter->idx);
> +       base = validate_displayid(displayid, iter->length, iter->idx, 
> ignore_checksum);
>         if (IS_ERR(base))
>                 return NULL;
>
> @@ -76,6 +108,7 @@ void displayid_iter_edid_begin(const struct drm_edid 
> *drm_edid,
>         memset(iter, 0, sizeof(*iter));
>
>         iter->drm_edid = drm_edid;
> +       iter->quirks = get_quirks(drm_edid);
>  }
>
>  static const struct displayid_block *
> diff --git a/drivers/gpu/drm/drm_displayid_internal.h 
> b/drivers/gpu/drm/drm_displayid_internal.h
> index 957dd0619f5c..5b1b32f73516 100644
> --- a/drivers/gpu/drm/drm_displayid_internal.h
> +++ b/drivers/gpu/drm/drm_displayid_internal.h
> @@ -167,6 +167,8 @@ struct displayid_iter {
>
>         u8 version;
>         u8 primary_use;
> +
> +       u8 quirks;
>  };
>
>  void displayid_iter_edid_begin(const struct drm_edid *drm_edid,
> --
> 2.47.3
>

Reply via email to