On Fri, 2024-08-30 at 15:16 +0300, Jani Nikula wrote: > On Fri, 23 Aug 2024, Jouni Högander <jouni.hogander@xxxxxxxxx> wrote: > > Currently there is no way to apply quirk on device only if certain > > panel > > model is installed. This patch implements such mechanism by adding > > new > > quirk type intel_dpcd_quirk which contains also sink_oui and > > sink_device_id > > fields and using also them to figure out if applying quirk is > > needed. > > > > New intel_init_dpcd_quirks is added and called after > > drm_dp_read_desc with > > proper sink device identity read from dpcdc. > > > > v2: > > - instead of using struct intel_quirk add new struct > > intel_dpcd_quirk > > > > Signed-off-by: Jouni Högander <jouni.hogander@xxxxxxxxx> > > --- > > .../drm/i915/display/intel_display_types.h | 4 ++ > > drivers/gpu/drm/i915/display/intel_dp.c | 4 ++ > > drivers/gpu/drm/i915/display/intel_quirks.c | 51 > > +++++++++++++++++++ > > drivers/gpu/drm/i915/display/intel_quirks.h | 5 ++ > > 4 files changed, 64 insertions(+) > > > > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h > > b/drivers/gpu/drm/i915/display/intel_display_types.h > > index bd290536a1b7b..767ee6da8b1a4 100644 > > --- a/drivers/gpu/drm/i915/display/intel_display_types.h > > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h > > @@ -1907,6 +1907,10 @@ struct intel_dp { > > } alpm_parameters; > > > > u8 alpm_dpcd; > > + > > + struct { > > + unsigned long mask; > > + } quirks; > > }; > > > > enum lspcon_vendor { > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c > > b/drivers/gpu/drm/i915/display/intel_dp.c > > index 6a0c7ae654f40..a878ff6f3581d 100644 > > --- a/drivers/gpu/drm/i915/display/intel_dp.c > > +++ b/drivers/gpu/drm/i915/display/intel_dp.c > > @@ -84,6 +84,7 @@ > > #include "intel_pch_display.h" > > #include "intel_pps.h" > > #include "intel_psr.h" > > +#include "intel_quirks.h" > > #include "intel_tc.h" > > #include "intel_vdsc.h" > > #include "intel_vrr.h" > > @@ -4053,6 +4054,7 @@ intel_edp_init_dpcd(struct intel_dp > > *intel_dp, struct intel_connector *connector > > > > drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc, > > drm_dp_is_branch(intel_dp->dpcd)); > > + intel_init_dpcd_quirks(intel_dp, &intel_dp->desc.ident); > > > > /* > > * Read the eDP display control registers. > > @@ -4165,6 +4167,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) > > drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc, > > drm_dp_is_branch(intel_dp->dpcd)); > > > > + intel_init_dpcd_quirks(intel_dp, &intel_dp- > > >desc.ident); > > + > > intel_dp_update_sink_caps(intel_dp); > > } > > > > diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c > > b/drivers/gpu/drm/i915/display/intel_quirks.c > > index 14d5fefc9c5b2..973da787ea2d9 100644 > > --- a/drivers/gpu/drm/i915/display/intel_quirks.c > > +++ b/drivers/gpu/drm/i915/display/intel_quirks.c > > @@ -14,6 +14,11 @@ static void intel_set_quirk(struct intel_display > > *display, enum intel_quirk_id q > > display->quirks.mask |= BIT(quirk); > > } > > > > +static void intel_set_dpcd_quirk(struct intel_dp *intel_dp, enum > > intel_quirk_id quirk) > > +{ > > + intel_dp->quirks.mask |= BIT(quirk); > > +} > > + > > /* > > * Some machines (Lenovo U160) do not work with SSC on LVDS for > > some reason > > */ > > @@ -72,6 +77,21 @@ struct intel_quirk { > > void (*hook)(struct intel_display *display); > > }; > > > > +struct intel_dpcd_quirk { > > + int device; > > + int subsystem_vendor; > > + int subsystem_device; > > + u8 sink_oui[3]; > > + u8 sink_device_id[6]; > > + void (*hook)(struct intel_dp *intel_dp); > > +}; > > + > > +#define SINK_OUI(first, second, third) { (first), (second), > > (third) } > > +#define SINK_DEVICE_ID(first, second, third, fourth, fifth, sixth) > > \ > > + { (first), (second), (third), (fourth), (fifth), (sixth) } > > + > > +#define SINK_DEVICE_ID_ANY SINK_DEVICE_ID(0, 0, 0, 0, 0, 0) > > + > > /* For systems that don't have a meaningful PCI > > subdevice/subvendor ID */ > > struct intel_dmi_quirk { > > void (*hook)(struct intel_display *display); > > @@ -203,6 +223,9 @@ static struct intel_quirk intel_quirks[] = { > > { 0x0f31, 0x103c, 0x220f, quirk_invert_brightness }, > > }; > > > > +static struct intel_dpcd_quirk intel_dpcd_quirks[] = { > > +}; > > + > > void intel_init_quirks(struct intel_display *display) > > { > > struct pci_dev *d = to_pci_dev(display->drm->dev); > > @@ -224,7 +247,35 @@ void intel_init_quirks(struct intel_display > > *display) > > } > > } > > > > +void intel_init_dpcd_quirks(struct intel_dp *intel_dp, > > + const struct drm_dp_dpcd_ident *ident) > > +{ > > + struct intel_display *display = to_intel_display(intel_dp); > > + struct pci_dev *d = to_pci_dev(display->drm->dev); > > + int i; > > + > > + for (i = 0; i < ARRAY_SIZE(intel_dpcd_quirks); i++) { > > + struct intel_dpcd_quirk *q = &intel_dpcd_quirks[i]; > > + > > + if (d->device == q->device && > > + (d->subsystem_vendor == q->subsystem_vendor || > > + q->subsystem_vendor == PCI_ANY_ID) && > > + (d->subsystem_device == q->subsystem_device || > > + q->subsystem_device == PCI_ANY_ID) && > > + !memcmp(q->sink_oui, ident->oui, sizeof(ident- > > >oui)) && > > + (!memcmp(q->sink_device_id, ident->device_id, > > + sizeof(ident->device_id)) || > > + !mem_is_zero(q->sink_device_id, sizeof(q- > > >sink_device_id)))) > > Should that be mem_is_zero() instead of !mem_is_zero()? Yes that should be mem_is_zero(). Thank you for this catch. BR, Jouni Högander > > BR, > Jani. > > > + q->hook(intel_dp); > > + } > > +} > > + > > bool intel_has_quirk(struct intel_display *display, enum > > intel_quirk_id quirk) > > { > > return display->quirks.mask & BIT(quirk); > > } > > + > > +bool intel_has_dpcd_quirk(struct intel_dp *intel_dp, enum > > intel_quirk_id quirk) > > +{ > > + return intel_dp->quirks.mask & BIT(quirk); > > +} > > diff --git a/drivers/gpu/drm/i915/display/intel_quirks.h > > b/drivers/gpu/drm/i915/display/intel_quirks.h > > index 151c8f4ae5760..c8db50b9ab74d 100644 > > --- a/drivers/gpu/drm/i915/display/intel_quirks.h > > +++ b/drivers/gpu/drm/i915/display/intel_quirks.h > > @@ -9,6 +9,8 @@ > > #include <linux/types.h> > > > > struct intel_display; > > +struct intel_dp; > > +struct drm_dp_dpcd_ident; > > > > enum intel_quirk_id { > > QUIRK_BACKLIGHT_PRESENT, > > @@ -20,6 +22,9 @@ enum intel_quirk_id { > > }; > > > > void intel_init_quirks(struct intel_display *display); > > +void intel_init_dpcd_quirks(struct intel_dp *intel_dp, > > + const struct drm_dp_dpcd_ident *ident); > > bool intel_has_quirk(struct intel_display *display, enum > > intel_quirk_id quirk); > > +bool intel_has_dpcd_quirk(struct intel_dp *intel_dp, enum > > intel_quirk_id quirk); > > > > #endif /* __INTEL_QUIRKS_H__ */ >