Message ID | 20240823124725.424291-2-jouni.hogander@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Increase fastwake sync pulse count as a quirk | expand |
On Fri, 23 Aug 2024, Jouni Högander <jouni.hogander@intel.com> 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@intel.com> > --- > .../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()? 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__ */
On Fri, 2024-08-30 at 15:16 +0300, Jani Nikula wrote: > On Fri, 23 Aug 2024, Jouni Högander <jouni.hogander@intel.com> 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@intel.com> > > --- > > .../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__ */ >
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)))) + 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__ */
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@intel.com> --- .../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(+)