* [PATCH] drm/edid: Handle EDID 1.4 range descriptor h/vfreq offsets @ 2022-08-19 9:27 Ville Syrjala 2022-08-23 17:15 ` Jani Nikula 2022-08-24 13:46 ` [PATCH v2] " Ville Syrjala 0 siblings, 2 replies; 4+ messages in thread From: Ville Syrjala @ 2022-08-19 9:27 UTC (permalink / raw) To: dri-devel; +Cc: intel-gfx, stable From: Ville Syrjälä <ville.syrjala@linux.intel.com> EDID 1.4 introduced some extra flags in the range descriptor to support min/max h/vfreq >= 255. Consult them to correctly parse the vfreq limits. Cc: stable@vger.kernel.org Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6519 Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> --- drivers/gpu/drm/drm_edid.c | 24 ++++++++++++++++++------ include/drm/drm_edid.h | 5 +++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 90a5e26eafa8..4005dab6147d 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -6020,12 +6020,14 @@ static void drm_parse_cea_ext(struct drm_connector *connector, } static -void get_monitor_range(const struct detailed_timing *timing, - void *info_monitor_range) +void get_monitor_range(const struct detailed_timing *timing, void *c) { - struct drm_monitor_range_info *monitor_range = info_monitor_range; + struct detailed_mode_closure *closure = c; + struct drm_display_info *info = &closure->connector->display_info; + struct drm_monitor_range_info *monitor_range = &info->monitor_range; const struct detailed_non_pixel *data = &timing->data.other_data; const struct detailed_data_monitor_range *range = &data->data.range; + const struct edid *edid = closure->drm_edid->edid; if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE)) return; @@ -6041,18 +6043,28 @@ void get_monitor_range(const struct detailed_timing *timing, monitor_range->min_vfreq = range->min_vfreq; monitor_range->max_vfreq = range->max_vfreq; + + if (edid->revision >= 4) { + if (data->pad2 & DRM_EDID_RANGE_OFFSET_MIN_VFREQ) + monitor_range->min_vfreq += 255; + if (data->pad2 & DRM_EDID_RANGE_OFFSET_MAX_VFREQ) + monitor_range->max_vfreq += 255; + } } static void drm_get_monitor_range(struct drm_connector *connector, const struct drm_edid *drm_edid) { - struct drm_display_info *info = &connector->display_info; + const struct drm_display_info *info = &connector->display_info; + struct detailed_mode_closure closure = { + .connector = connector, + .drm_edid = drm_edid, + }; if (!version_greater(drm_edid, 1, 1)) return; - drm_for_each_detailed_block(drm_edid, get_monitor_range, - &info->monitor_range); + drm_for_each_detailed_block(drm_edid, get_monitor_range, &closure); DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n", info->monitor_range.min_vfreq, diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 2181977ae683..d81da97cad6e 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -92,6 +92,11 @@ struct detailed_data_string { u8 str[13]; } __attribute__((packed)); +#define DRM_EDID_RANGE_OFFSET_MIN_VFREQ (1 << 0) +#define DRM_EDID_RANGE_OFFSET_MAX_VFREQ (1 << 1) +#define DRM_EDID_RANGE_OFFSET_MIN_HFREQ (1 << 2) +#define DRM_EDID_RANGE_OFFSET_MAX_HFREQ (1 << 3) + #define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG 0x00 #define DRM_EDID_RANGE_LIMITS_ONLY_FLAG 0x01 #define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02 -- 2.35.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] drm/edid: Handle EDID 1.4 range descriptor h/vfreq offsets 2022-08-19 9:27 [PATCH] drm/edid: Handle EDID 1.4 range descriptor h/vfreq offsets Ville Syrjala @ 2022-08-23 17:15 ` Jani Nikula 2022-08-24 12:11 ` Ville Syrjälä 2022-08-24 13:46 ` [PATCH v2] " Ville Syrjala 1 sibling, 1 reply; 4+ messages in thread From: Jani Nikula @ 2022-08-23 17:15 UTC (permalink / raw) To: Ville Syrjala, dri-devel; +Cc: intel-gfx, stable On Fri, 19 Aug 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote: > From: Ville Syrjälä <ville.syrjala@linux.intel.com> > > EDID 1.4 introduced some extra flags in the range > descriptor to support min/max h/vfreq >= 255. Consult them > to correctly parse the vfreq limits. > > Cc: stable@vger.kernel.org > Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6519 > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> > --- > drivers/gpu/drm/drm_edid.c | 24 ++++++++++++++++++------ > include/drm/drm_edid.h | 5 +++++ > 2 files changed, 23 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c > index 90a5e26eafa8..4005dab6147d 100644 > --- a/drivers/gpu/drm/drm_edid.c > +++ b/drivers/gpu/drm/drm_edid.c > @@ -6020,12 +6020,14 @@ static void drm_parse_cea_ext(struct drm_connector *connector, > } > > static > -void get_monitor_range(const struct detailed_timing *timing, > - void *info_monitor_range) > +void get_monitor_range(const struct detailed_timing *timing, void *c) > { > - struct drm_monitor_range_info *monitor_range = info_monitor_range; > + struct detailed_mode_closure *closure = c; > + struct drm_display_info *info = &closure->connector->display_info; > + struct drm_monitor_range_info *monitor_range = &info->monitor_range; > const struct detailed_non_pixel *data = &timing->data.other_data; > const struct detailed_data_monitor_range *range = &data->data.range; > + const struct edid *edid = closure->drm_edid->edid; > > if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE)) > return; > @@ -6041,18 +6043,28 @@ void get_monitor_range(const struct detailed_timing *timing, > > monitor_range->min_vfreq = range->min_vfreq; > monitor_range->max_vfreq = range->max_vfreq; > + > + if (edid->revision >= 4) { > + if (data->pad2 & DRM_EDID_RANGE_OFFSET_MIN_VFREQ) > + monitor_range->min_vfreq += 255; > + if (data->pad2 & DRM_EDID_RANGE_OFFSET_MAX_VFREQ) > + monitor_range->max_vfreq += 255; > + } Nitpick, a combo where min vertical range has +255 offset but max doesn't shouldn't be okay. But then, what are we going to do in that case anyway? I guess the generic check would be min <= max. Also, the +255 offset range is 256..510, not 256..(255+255). Again, what to do if that's what the EDID has? *shrug*. Anyway, what's broken here (and probably impacts the testing in the referenced bug) is that the struct drm_monitor_range_info members are u8 and this overflows. With that fixed, whether or not you decide to do anything about the nitpicks, Reviewed-by: Jani Nikula <jani.nikula@intel.com> Side note, git grep for monitor_range reveals amdgpu are doing their own thing for the parsing. *sigh*. > } > > static void drm_get_monitor_range(struct drm_connector *connector, > const struct drm_edid *drm_edid) > { > - struct drm_display_info *info = &connector->display_info; > + const struct drm_display_info *info = &connector->display_info; > + struct detailed_mode_closure closure = { > + .connector = connector, > + .drm_edid = drm_edid, > + }; > > if (!version_greater(drm_edid, 1, 1)) > return; > > - drm_for_each_detailed_block(drm_edid, get_monitor_range, > - &info->monitor_range); > + drm_for_each_detailed_block(drm_edid, get_monitor_range, &closure); > > DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n", > info->monitor_range.min_vfreq, > diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h > index 2181977ae683..d81da97cad6e 100644 > --- a/include/drm/drm_edid.h > +++ b/include/drm/drm_edid.h > @@ -92,6 +92,11 @@ struct detailed_data_string { > u8 str[13]; > } __attribute__((packed)); > > +#define DRM_EDID_RANGE_OFFSET_MIN_VFREQ (1 << 0) > +#define DRM_EDID_RANGE_OFFSET_MAX_VFREQ (1 << 1) > +#define DRM_EDID_RANGE_OFFSET_MIN_HFREQ (1 << 2) > +#define DRM_EDID_RANGE_OFFSET_MAX_HFREQ (1 << 3) > + > #define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG 0x00 > #define DRM_EDID_RANGE_LIMITS_ONLY_FLAG 0x01 > #define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02 -- Jani Nikula, Intel Open Source Graphics Center ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] drm/edid: Handle EDID 1.4 range descriptor h/vfreq offsets 2022-08-23 17:15 ` Jani Nikula @ 2022-08-24 12:11 ` Ville Syrjälä 0 siblings, 0 replies; 4+ messages in thread From: Ville Syrjälä @ 2022-08-24 12:11 UTC (permalink / raw) To: Jani Nikula; +Cc: dri-devel, intel-gfx, stable On Tue, Aug 23, 2022 at 08:15:48PM +0300, Jani Nikula wrote: > On Fri, 19 Aug 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote: > > From: Ville Syrjälä <ville.syrjala@linux.intel.com> > > > > EDID 1.4 introduced some extra flags in the range > > descriptor to support min/max h/vfreq >= 255. Consult them > > to correctly parse the vfreq limits. > > > > Cc: stable@vger.kernel.org > > Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6519 > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> > > --- > > drivers/gpu/drm/drm_edid.c | 24 ++++++++++++++++++------ > > include/drm/drm_edid.h | 5 +++++ > > 2 files changed, 23 insertions(+), 6 deletions(-) > > > > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c > > index 90a5e26eafa8..4005dab6147d 100644 > > --- a/drivers/gpu/drm/drm_edid.c > > +++ b/drivers/gpu/drm/drm_edid.c > > @@ -6020,12 +6020,14 @@ static void drm_parse_cea_ext(struct drm_connector *connector, > > } > > > > static > > -void get_monitor_range(const struct detailed_timing *timing, > > - void *info_monitor_range) > > +void get_monitor_range(const struct detailed_timing *timing, void *c) > > { > > - struct drm_monitor_range_info *monitor_range = info_monitor_range; > > + struct detailed_mode_closure *closure = c; > > + struct drm_display_info *info = &closure->connector->display_info; > > + struct drm_monitor_range_info *monitor_range = &info->monitor_range; > > const struct detailed_non_pixel *data = &timing->data.other_data; > > const struct detailed_data_monitor_range *range = &data->data.range; > > + const struct edid *edid = closure->drm_edid->edid; > > > > if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE)) > > return; > > @@ -6041,18 +6043,28 @@ void get_monitor_range(const struct detailed_timing *timing, > > > > monitor_range->min_vfreq = range->min_vfreq; > > monitor_range->max_vfreq = range->max_vfreq; > > + > > + if (edid->revision >= 4) { > > + if (data->pad2 & DRM_EDID_RANGE_OFFSET_MIN_VFREQ) > > + monitor_range->min_vfreq += 255; > > + if (data->pad2 & DRM_EDID_RANGE_OFFSET_MAX_VFREQ) > > + monitor_range->max_vfreq += 255; > > + } > > Nitpick, a combo where min vertical range has +255 offset but max > doesn't shouldn't be okay. But then, what are we going to do in that > case anyway? I guess the generic check would be min <= max. Also, the > +255 offset range is 256..510, not 256..(255+255). Again, what to do if > that's what the EDID has? *shrug*. Yeah, I figured that writing the code in the most straightforward way was fine since reserved values aren't going to produce valid results anyway. Though I guess just ignoring the whole descriptor in that case might be another option. > > Anyway, what's broken here (and probably impacts the testing in the > referenced bug) is that the struct drm_monitor_range_info members are u8 > and this overflows. Derp. > > With that fixed, whether or not you decide to do anything about the > nitpicks, > > Reviewed-by: Jani Nikula <jani.nikula@intel.com> Thanks. > > > Side note, git grep for monitor_range reveals amdgpu are doing their own > thing for the parsing. *sigh*. > > > > } > > > > static void drm_get_monitor_range(struct drm_connector *connector, > > const struct drm_edid *drm_edid) > > { > > - struct drm_display_info *info = &connector->display_info; > > + const struct drm_display_info *info = &connector->display_info; > > + struct detailed_mode_closure closure = { > > + .connector = connector, > > + .drm_edid = drm_edid, > > + }; > > > > if (!version_greater(drm_edid, 1, 1)) > > return; > > > > - drm_for_each_detailed_block(drm_edid, get_monitor_range, > > - &info->monitor_range); > > + drm_for_each_detailed_block(drm_edid, get_monitor_range, &closure); > > > > DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n", > > info->monitor_range.min_vfreq, > > diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h > > index 2181977ae683..d81da97cad6e 100644 > > --- a/include/drm/drm_edid.h > > +++ b/include/drm/drm_edid.h > > @@ -92,6 +92,11 @@ struct detailed_data_string { > > u8 str[13]; > > } __attribute__((packed)); > > > > +#define DRM_EDID_RANGE_OFFSET_MIN_VFREQ (1 << 0) > > +#define DRM_EDID_RANGE_OFFSET_MAX_VFREQ (1 << 1) > > +#define DRM_EDID_RANGE_OFFSET_MIN_HFREQ (1 << 2) > > +#define DRM_EDID_RANGE_OFFSET_MAX_HFREQ (1 << 3) > > + > > #define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG 0x00 > > #define DRM_EDID_RANGE_LIMITS_ONLY_FLAG 0x01 > > #define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02 > > -- > Jani Nikula, Intel Open Source Graphics Center -- Ville Syrjälä Intel ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2] drm/edid: Handle EDID 1.4 range descriptor h/vfreq offsets 2022-08-19 9:27 [PATCH] drm/edid: Handle EDID 1.4 range descriptor h/vfreq offsets Ville Syrjala 2022-08-23 17:15 ` Jani Nikula @ 2022-08-24 13:46 ` Ville Syrjala 1 sibling, 0 replies; 4+ messages in thread From: Ville Syrjala @ 2022-08-24 13:46 UTC (permalink / raw) To: dri-devel; +Cc: intel-gfx, stable, Jani Nikula From: Ville Syrjälä <ville.syrjala@linux.intel.com> EDID 1.4 introduced some extra flags in the range descriptor to support min/max h/vfreq >= 255. Consult them to correctly parse the vfreq limits. Note that some combinations of the flags are documented as "reserved" (as are some other values in the descriptor) but explicitly checking for those doesn't seem particularly worthwile since we end up with bogus results whether we decode them or not. v2: Increase the storage to u16 to make it work (Jani) Note the "reserved" values situation (Jani) Cc: stable@vger.kernel.org Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6519 Reviewed-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> --- drivers/gpu/drm/drm_edid.c | 24 ++++++++++++++++++------ include/drm/drm_connector.h | 4 ++-- include/drm/drm_edid.h | 5 +++++ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 90a5e26eafa8..4005dab6147d 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -6020,12 +6020,14 @@ static void drm_parse_cea_ext(struct drm_connector *connector, } static -void get_monitor_range(const struct detailed_timing *timing, - void *info_monitor_range) +void get_monitor_range(const struct detailed_timing *timing, void *c) { - struct drm_monitor_range_info *monitor_range = info_monitor_range; + struct detailed_mode_closure *closure = c; + struct drm_display_info *info = &closure->connector->display_info; + struct drm_monitor_range_info *monitor_range = &info->monitor_range; const struct detailed_non_pixel *data = &timing->data.other_data; const struct detailed_data_monitor_range *range = &data->data.range; + const struct edid *edid = closure->drm_edid->edid; if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE)) return; @@ -6041,18 +6043,28 @@ void get_monitor_range(const struct detailed_timing *timing, monitor_range->min_vfreq = range->min_vfreq; monitor_range->max_vfreq = range->max_vfreq; + + if (edid->revision >= 4) { + if (data->pad2 & DRM_EDID_RANGE_OFFSET_MIN_VFREQ) + monitor_range->min_vfreq += 255; + if (data->pad2 & DRM_EDID_RANGE_OFFSET_MAX_VFREQ) + monitor_range->max_vfreq += 255; + } } static void drm_get_monitor_range(struct drm_connector *connector, const struct drm_edid *drm_edid) { - struct drm_display_info *info = &connector->display_info; + const struct drm_display_info *info = &connector->display_info; + struct detailed_mode_closure closure = { + .connector = connector, + .drm_edid = drm_edid, + }; if (!version_greater(drm_edid, 1, 1)) return; - drm_for_each_detailed_block(drm_edid, get_monitor_range, - &info->monitor_range); + drm_for_each_detailed_block(drm_edid, get_monitor_range, &closure); DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n", info->monitor_range.min_vfreq, diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 248206bbd975..56aee949c6fa 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -319,8 +319,8 @@ enum drm_panel_orientation { * EDID's detailed monitor range */ struct drm_monitor_range_info { - u8 min_vfreq; - u8 max_vfreq; + u16 min_vfreq; + u16 max_vfreq; }; /** diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 2181977ae683..d81da97cad6e 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -92,6 +92,11 @@ struct detailed_data_string { u8 str[13]; } __attribute__((packed)); +#define DRM_EDID_RANGE_OFFSET_MIN_VFREQ (1 << 0) +#define DRM_EDID_RANGE_OFFSET_MAX_VFREQ (1 << 1) +#define DRM_EDID_RANGE_OFFSET_MIN_HFREQ (1 << 2) +#define DRM_EDID_RANGE_OFFSET_MAX_HFREQ (1 << 3) + #define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG 0x00 #define DRM_EDID_RANGE_LIMITS_ONLY_FLAG 0x01 #define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02 -- 2.35.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-08-24 13:52 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-08-19 9:27 [PATCH] drm/edid: Handle EDID 1.4 range descriptor h/vfreq offsets Ville Syrjala 2022-08-23 17:15 ` Jani Nikula 2022-08-24 12:11 ` Ville Syrjälä 2022-08-24 13:46 ` [PATCH v2] " Ville Syrjala
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox