On Thu, 30 Oct 2025, Alex Deucher <[email protected]> wrote:
> 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]>
Thanks, pushed to drm-misc-next.
BR,
Jani.
>
>> ---
>> 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
>>
--
Jani Nikula, Intel