Introduce struct drm_edid and start converting struct edid * to struct drm_edid * in the EDID parsing. The rationale for drm_edid is explained in depth in commit message for patch 3.
Initially, there's little functional benefit in the series, it's mostly just prep work. It's also intended to be relatively straightforward to review.
Later on, we'll add interfaces around drm_edid that let us utilize the actual EDID buffer allocation size as metadata outside of the size contained within the EDID blob. This is a requirement for safely handling HF-EEODB without a huge flag day switch from struct edid usage. See [1] for that work.
BR, Jani.
[1] https://cgit.freedesktop.org/~jani/drm/log/?h=edid-hfeeodb-2022-05-06
Jani Nikula (25): drm/edid: use else-if in CTA extension parsing drm/edid: convert drm_for_each_detailed_block() to edid iter drm/edid: add struct drm_edid container drm/edid: start propagating drm_edid to lower levels drm/edid: keep propagating drm_edid to display info drm/edid: propagate drm_edid to drm_edid_to_eld() drm/edid: convert drm_edid_connector_update() to drm_edid fully drm/edid: convert struct detailed_mode_closure to drm_edid drm/edid: convert drm_mode_detailed() to drm_edid drm/edid: convert drm_dmt_modes_for_range() to drm_edid drm/edid: convert drm_gtf_modes_for_range() to drm_edid drm/edid: convert drm_cvt_modes_for_range() to drm_edid drm/edid: convert drm_mode_std() and children to drm_edid drm/edid: convert mode_in_range() and drm_monitor_supports_rb() to drm_edid drm/edid: convert get_monitor_name() to drm_edid drm/edid: convert drm_for_each_detailed_block() to drm_edid drm/edid: add drm_edid helper for drm_edid_to_sad() drm/edid: add drm_edid helper for drm_edid_to_speaker_allocation() drm/edid: add drm_edid helper for drm_detect_hdmi_monitor() drm/edid: add drm_edid helper for drm_detect_monitor_audio() drm/edid: convert cea_db_iter_edid_begin() to drm_edid drm/edid: convert drm_edid_iter_begin() to drm_edid drm/edid: add drm_edid helper for drm_update_tile_info() drm/displayid: convert to drm_edid drm/edid: convert version_greater() to drm_edid
drivers/gpu/drm/drm_displayid.c | 16 +- drivers/gpu/drm/drm_edid.c | 542 +++++++++++++++++++------------- include/drm/drm_displayid.h | 6 +- include/drm/drm_edid.h | 6 +- 4 files changed, 337 insertions(+), 233 deletions(-)
Only one of the conditions can be true.
Suggested-by: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 47d121e99201..efc1999b9573 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -5473,16 +5473,16 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
if (cea_db_is_hdmi_vsdb(db)) drm_parse_hdmi_vsdb_video(connector, data); - if (cea_db_is_hdmi_forum_vsdb(db) || - cea_db_is_hdmi_forum_scdb(db)) + else if (cea_db_is_hdmi_forum_vsdb(db) || + cea_db_is_hdmi_forum_scdb(db)) drm_parse_hdmi_forum_scds(connector, data); - if (cea_db_is_microsoft_vsdb(db)) + else if (cea_db_is_microsoft_vsdb(db)) drm_parse_microsoft_vsdb(connector, data); - if (cea_db_is_y420cmdb(db)) + else if (cea_db_is_y420cmdb(db)) drm_parse_y420cmdb_bitmap(connector, data); - if (cea_db_is_vcdb(db)) + else if (cea_db_is_vcdb(db)) drm_parse_vcdb(connector, data); - if (cea_db_is_hdmi_hdr_metadata_block(db)) + else if (cea_db_is_hdmi_hdr_metadata_block(db)) drm_parse_hdr_metadata_block(connector, data); } cea_db_iter_end(&iter);
On Fri, May 06, 2022 at 01:10:08PM +0300, Jani Nikula wrote:
Only one of the conditions can be true.
Suggested-by: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Jani Nikula jani.nikula@intel.com
Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
drivers/gpu/drm/drm_edid.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 47d121e99201..efc1999b9573 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -5473,16 +5473,16 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
if (cea_db_is_hdmi_vsdb(db)) drm_parse_hdmi_vsdb_video(connector, data);
if (cea_db_is_hdmi_forum_vsdb(db) ||
cea_db_is_hdmi_forum_scdb(db))
else if (cea_db_is_hdmi_forum_vsdb(db) ||
cea_db_is_hdmi_forum_scdb(db)) drm_parse_hdmi_forum_scds(connector, data);
if (cea_db_is_microsoft_vsdb(db))
else if (cea_db_is_microsoft_vsdb(db)) drm_parse_microsoft_vsdb(connector, data);
if (cea_db_is_y420cmdb(db))
else if (cea_db_is_y420cmdb(db)) drm_parse_y420cmdb_bitmap(connector, data);
if (cea_db_is_vcdb(db))
else if (cea_db_is_vcdb(db)) drm_parse_vcdb(connector, data);
if (cea_db_is_hdmi_hdr_metadata_block(db))
} cea_db_iter_end(&iter);else if (cea_db_is_hdmi_hdr_metadata_block(db)) drm_parse_hdr_metadata_block(connector, data);
-- 2.30.2
We have an iterator for this, use it. It does include the base block, but its tag is 0 and will be skipped.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index efc1999b9573..dcef92c8887a 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2574,6 +2574,8 @@ vtb_for_each_detailed_block(const u8 *ext, detailed_cb *cb, void *closure) static void drm_for_each_detailed_block(const struct edid *edid, detailed_cb *cb, void *closure) { + struct drm_edid_iter edid_iter; + const u8 *ext; int i;
if (edid == NULL) @@ -2582,9 +2584,8 @@ drm_for_each_detailed_block(const struct edid *edid, detailed_cb *cb, void *clos for (i = 0; i < EDID_DETAILED_TIMINGS; i++) cb(&(edid->detailed_timings[i]), closure);
- for (i = 0; i < edid_extension_block_count(edid); i++) { - const u8 *ext = edid_extension_block_data(edid, i); - + drm_edid_iter_begin(edid, &edid_iter); + drm_edid_iter_for_each(ext, &edid_iter) { switch (*ext) { case CEA_EXT: cea_for_each_detailed_block(ext, cb, closure); @@ -2596,6 +2597,7 @@ drm_for_each_detailed_block(const struct edid *edid, detailed_cb *cb, void *clos break; } } + drm_edid_iter_end(&edid_iter); }
static void
On Fri, May 06, 2022 at 01:10:09PM +0300, Jani Nikula wrote:
We have an iterator for this, use it. It does include the base block, but its tag is 0 and will be skipped.
Signed-off-by: Jani Nikula jani.nikula@intel.com
Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
drivers/gpu/drm/drm_edid.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index efc1999b9573..dcef92c8887a 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2574,6 +2574,8 @@ vtb_for_each_detailed_block(const u8 *ext, detailed_cb *cb, void *closure) static void drm_for_each_detailed_block(const struct edid *edid, detailed_cb *cb, void *closure) {
struct drm_edid_iter edid_iter;
const u8 *ext; int i;
if (edid == NULL)
@@ -2582,9 +2584,8 @@ drm_for_each_detailed_block(const struct edid *edid, detailed_cb *cb, void *clos for (i = 0; i < EDID_DETAILED_TIMINGS; i++) cb(&(edid->detailed_timings[i]), closure);
- for (i = 0; i < edid_extension_block_count(edid); i++) {
const u8 *ext = edid_extension_block_data(edid, i);
- drm_edid_iter_begin(edid, &edid_iter);
- drm_edid_iter_for_each(ext, &edid_iter) { switch (*ext) { case CEA_EXT: cea_for_each_detailed_block(ext, cb, closure);
@@ -2596,6 +2597,7 @@ drm_for_each_detailed_block(const struct edid *edid, detailed_cb *cb, void *clos break; } }
- drm_edid_iter_end(&edid_iter);
}
static void
2.30.2
Introduce new opaque type struct drm_edid to encapsulate the EDID data and the size allocated for it. The contents will be private to drm_edid.c.
There are a number of reasons for adding a container around struct edid:
* struct edid is a raw blob pointer to data that usually originates outside of the kernel. Its size is contained within the structure.
* There's no way to attach meta information (such as allocated memory size) to struct edid.
* Validation of the EDID blob and its size become crucial, and it's spread all over the subsystem, with varying levels of accuracy.
* HDMI Forum has introduced an HF-EEODB extension that defines an override EDID size within an EDID extension. The size allocated for an EDID depends on whether the allocator understands the HF-EEODB extension. Given a struct edid *, it's impossible to know how much memory was actually allocated for it.
There are also some reasons for making the container type struct drm_edid opaque and private to drm_edid.c:
* Have only one place for creating and parsing the EDID, to avoid duplicating bugs.
* Prepare for reading a pure DisplayID 2.0 from its own DDC address, and adding it within the same struct drm_edid container, transparently, and for all drivers.
* With the idea that the drm_edid objects are immutable during their lifetimes, it will be possible to refcount them and reduce EDID copying everywhere (this is left for future work).
Initially, just add the type. In follow-up, we'll start converting the guts of drm_edid.c to use it, and finally add interfaces around it.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index dcef92c8887a..480fd9fbe412 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1567,6 +1567,15 @@ static const struct drm_display_mode edid_4k_modes[] = {
/*** DDC fetch and block validation ***/
+/* + * The opaque EDID type, internal to drm_edid.c. + */ +struct drm_edid { + /* Size allocated for edid */ + size_t size; + const struct edid *edid; +}; + static int edid_extension_block_count(const struct edid *edid) { return edid->extensions;
LGTM.
Reviewed-by: Ankit Nautiyal ankit.k.nautiyal@intel.com
On 5/6/2022 3:40 PM, Jani Nikula wrote:
Introduce new opaque type struct drm_edid to encapsulate the EDID data and the size allocated for it. The contents will be private to drm_edid.c.
There are a number of reasons for adding a container around struct edid:
struct edid is a raw blob pointer to data that usually originates outside of the kernel. Its size is contained within the structure.
There's no way to attach meta information (such as allocated memory size) to struct edid.
Validation of the EDID blob and its size become crucial, and it's spread all over the subsystem, with varying levels of accuracy.
HDMI Forum has introduced an HF-EEODB extension that defines an override EDID size within an EDID extension. The size allocated for an EDID depends on whether the allocator understands the HF-EEODB extension. Given a struct edid *, it's impossible to know how much memory was actually allocated for it.
There are also some reasons for making the container type struct drm_edid opaque and private to drm_edid.c:
Have only one place for creating and parsing the EDID, to avoid duplicating bugs.
Prepare for reading a pure DisplayID 2.0 from its own DDC address, and adding it within the same struct drm_edid container, transparently, and for all drivers.
With the idea that the drm_edid objects are immutable during their lifetimes, it will be possible to refcount them and reduce EDID copying everywhere (this is left for future work).
Initially, just add the type. In follow-up, we'll start converting the guts of drm_edid.c to use it, and finally add interfaces around it.
Signed-off-by: Jani Nikula jani.nikula@intel.com
drivers/gpu/drm/drm_edid.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index dcef92c8887a..480fd9fbe412 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1567,6 +1567,15 @@ static const struct drm_display_mode edid_4k_modes[] = {
/*** DDC fetch and block validation ***/
+/*
- The opaque EDID type, internal to drm_edid.c.
- */
+struct drm_edid {
- /* Size allocated for edid */
- size_t size;
- const struct edid *edid;
+};
- static int edid_extension_block_count(const struct edid *edid) { return edid->extensions;
We'll need to propagate drm_edid everywhere. This is a clunky start, but a start nonetheless. We'll eventually convert all of the EDID parsing to struct drm_edid.
Initially, we'll just create the struct drm_edid in stack. This will be the compat layer for legacy struct edid code. In the future, we'll have EDID read return drm_edid objects.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 480fd9fbe412..946296632b2e 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -5814,17 +5814,20 @@ static int add_displayid_detailed_modes(struct drm_connector *connector, }
static int drm_edid_connector_update(struct drm_connector *connector, - const struct edid *edid) + const struct drm_edid *drm_edid) { + const struct edid *edid; int num_modes = 0; u32 quirks;
- if (edid == NULL) { + if (drm_edid == NULL) { drm_reset_display_info(connector); clear_eld(connector); return 0; }
+ edid = drm_edid->edid; + /* * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks. * To avoid multiple parsing of same block, lets parse that map @@ -5890,13 +5893,20 @@ static int drm_edid_connector_update(struct drm_connector *connector, */ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) { + struct drm_edid drm_edid = {}; + if (edid && !drm_edid_is_valid(edid)) { drm_warn(connector->dev, "%s: EDID invalid.\n", connector->name); edid = NULL; }
- return drm_edid_connector_update(connector, edid); + if (edid) { + drm_edid.edid = edid; + drm_edid.size = edid_size(edid); + } + + return drm_edid_connector_update(connector, edid ? &drm_edid : NULL); } EXPORT_SYMBOL(drm_add_edid_modes);
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 50 +++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 946296632b2e..c9d48fbd0a76 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2419,13 +2419,13 @@ EXPORT_SYMBOL(drm_edid_duplicate);
/** * edid_get_quirks - return quirk flags for a given EDID - * @edid: EDID to process + * @drm_edid: EDID to process * * This tells subsequent routines what fixes they need to apply. */ -static u32 edid_get_quirks(const struct edid *edid) +static u32 edid_get_quirks(const struct drm_edid *drm_edid) { - u32 panel_id = edid_extract_panel_id(edid); + u32 panel_id = edid_extract_panel_id(drm_edid->edid); const struct edid_quirk *quirk; int i;
@@ -5448,7 +5448,7 @@ static void drm_parse_microsoft_vsdb(struct drm_connector *connector, }
static void drm_parse_cea_ext(struct drm_connector *connector, - const struct edid *edid) + const struct drm_edid *drm_edid) { struct drm_display_info *info = &connector->display_info; struct drm_edid_iter edid_iter; @@ -5456,7 +5456,7 @@ static void drm_parse_cea_ext(struct drm_connector *connector, struct cea_db_iter iter; const u8 *edid_ext;
- drm_edid_iter_begin(edid, &edid_iter); + drm_edid_iter_begin(drm_edid->edid, &edid_iter); drm_edid_iter_for_each(edid_ext, &edid_iter) { if (edid_ext[0] != CEA_EXT) continue; @@ -5477,7 +5477,7 @@ static void drm_parse_cea_ext(struct drm_connector *connector, } drm_edid_iter_end(&edid_iter);
- cea_db_iter_edid_begin(edid, &iter); + cea_db_iter_edid_begin(drm_edid->edid, &iter); cea_db_iter_for_each(db, &iter) { /* FIXME: convert parsers to use struct cea_db */ const u8 *data = (const u8 *)db; @@ -5523,16 +5523,15 @@ void get_monitor_range(const struct detailed_timing *timing, monitor_range->max_vfreq = range->max_vfreq; }
-static -void drm_get_monitor_range(struct drm_connector *connector, - const struct edid *edid) +static void drm_get_monitor_range(struct drm_connector *connector, + const struct drm_edid *drm_edid) { struct drm_display_info *info = &connector->display_info;
- if (!version_greater(edid, 1, 1)) + if (!version_greater(drm_edid->edid, 1, 1)) return;
- drm_for_each_detailed_block(edid, get_monitor_range, + drm_for_each_detailed_block(drm_edid->edid, get_monitor_range, &info->monitor_range);
DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n", @@ -5592,12 +5591,13 @@ static void drm_parse_vesa_mso_data(struct drm_connector *connector, info->mso_stream_count, info->mso_pixel_overlap); }
-static void drm_update_mso(struct drm_connector *connector, const struct edid *edid) +static void drm_update_mso(struct drm_connector *connector, + const struct drm_edid *drm_edid) { const struct displayid_block *block; struct displayid_iter iter;
- displayid_iter_edid_begin(edid, &iter); + displayid_iter_edid_begin(drm_edid->edid, &iter); displayid_iter_for_each(block, &iter) { if (block->tag == DATA_BLOCK_2_VENDOR_SPECIFIC) drm_parse_vesa_mso_data(connector, block); @@ -5636,18 +5636,20 @@ drm_reset_display_info(struct drm_connector *connector) info->mso_pixel_overlap = 0; }
-u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid) +static u32 update_display_info(struct drm_connector *connector, + const struct drm_edid *drm_edid) { struct drm_display_info *info = &connector->display_info; + const struct edid *edid = drm_edid->edid;
- u32 quirks = edid_get_quirks(edid); + u32 quirks = edid_get_quirks(drm_edid);
drm_reset_display_info(connector);
info->width_mm = edid->width_cm * 10; info->height_mm = edid->height_cm * 10;
- drm_get_monitor_range(connector, edid); + drm_get_monitor_range(connector, drm_edid);
if (edid->revision < 3) goto out; @@ -5656,7 +5658,7 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi goto out;
info->color_formats |= DRM_COLOR_FORMAT_RGB444; - drm_parse_cea_ext(connector, edid); + drm_parse_cea_ext(connector, drm_edid);
/* * Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3? @@ -5709,7 +5711,7 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
- drm_update_mso(connector, edid); + drm_update_mso(connector, drm_edid);
out: if (quirks & EDID_QUIRK_NON_DESKTOP) { @@ -5721,6 +5723,16 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi return quirks; }
+u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid) +{ + struct drm_edid drm_edid = { + .edid = edid, + .size = edid_size(edid), + }; + + return update_display_info(connector, &drm_edid); +} + static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *dev, struct displayid_detailed_timings_1 *timings, bool type_7) @@ -5833,7 +5845,7 @@ static int drm_edid_connector_update(struct drm_connector *connector, * To avoid multiple parsing of same block, lets parse that map * from sink info, before parsing CEA modes. */ - quirks = drm_add_display_info(connector, edid); + quirks = update_display_info(connector, drm_edid);
/* Depends on info->cea_rev set by drm_add_display_info() above */ drm_edid_to_eld(connector, edid);
On Fri, 06 May 2022, Jani Nikula jani.nikula@intel.com wrote:
We'll need to propagate drm_edid everywhere.
I seem to have copy-pasted a TAB in some of the commit messages, in a way that does not show up in git log.
Signed-off-by: Jani Nikula jani.nikula@intel.com
drivers/gpu/drm/drm_edid.c | 50 +++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 946296632b2e..c9d48fbd0a76 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2419,13 +2419,13 @@ EXPORT_SYMBOL(drm_edid_duplicate);
/**
- edid_get_quirks - return quirk flags for a given EDID
- @edid: EDID to process
*/
- @drm_edid: EDID to process
- This tells subsequent routines what fixes they need to apply.
-static u32 edid_get_quirks(const struct edid *edid) +static u32 edid_get_quirks(const struct drm_edid *drm_edid) {
- u32 panel_id = edid_extract_panel_id(edid);
- u32 panel_id = edid_extract_panel_id(drm_edid->edid); const struct edid_quirk *quirk; int i;
@@ -5448,7 +5448,7 @@ static void drm_parse_microsoft_vsdb(struct drm_connector *connector, }
static void drm_parse_cea_ext(struct drm_connector *connector,
const struct edid *edid)
const struct drm_edid *drm_edid)
{ struct drm_display_info *info = &connector->display_info; struct drm_edid_iter edid_iter; @@ -5456,7 +5456,7 @@ static void drm_parse_cea_ext(struct drm_connector *connector, struct cea_db_iter iter; const u8 *edid_ext;
- drm_edid_iter_begin(edid, &edid_iter);
- drm_edid_iter_begin(drm_edid->edid, &edid_iter); drm_edid_iter_for_each(edid_ext, &edid_iter) { if (edid_ext[0] != CEA_EXT) continue;
@@ -5477,7 +5477,7 @@ static void drm_parse_cea_ext(struct drm_connector *connector, } drm_edid_iter_end(&edid_iter);
- cea_db_iter_edid_begin(edid, &iter);
- cea_db_iter_edid_begin(drm_edid->edid, &iter); cea_db_iter_for_each(db, &iter) { /* FIXME: convert parsers to use struct cea_db */ const u8 *data = (const u8 *)db;
@@ -5523,16 +5523,15 @@ void get_monitor_range(const struct detailed_timing *timing, monitor_range->max_vfreq = range->max_vfreq; }
-static -void drm_get_monitor_range(struct drm_connector *connector,
const struct edid *edid)
+static void drm_get_monitor_range(struct drm_connector *connector,
const struct drm_edid *drm_edid)
{ struct drm_display_info *info = &connector->display_info;
- if (!version_greater(edid, 1, 1))
- if (!version_greater(drm_edid->edid, 1, 1)) return;
- drm_for_each_detailed_block(edid, get_monitor_range,
drm_for_each_detailed_block(drm_edid->edid, get_monitor_range, &info->monitor_range);
DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n",
@@ -5592,12 +5591,13 @@ static void drm_parse_vesa_mso_data(struct drm_connector *connector, info->mso_stream_count, info->mso_pixel_overlap); }
-static void drm_update_mso(struct drm_connector *connector, const struct edid *edid) +static void drm_update_mso(struct drm_connector *connector,
const struct drm_edid *drm_edid)
{ const struct displayid_block *block; struct displayid_iter iter;
- displayid_iter_edid_begin(edid, &iter);
- displayid_iter_edid_begin(drm_edid->edid, &iter); displayid_iter_for_each(block, &iter) { if (block->tag == DATA_BLOCK_2_VENDOR_SPECIFIC) drm_parse_vesa_mso_data(connector, block);
@@ -5636,18 +5636,20 @@ drm_reset_display_info(struct drm_connector *connector) info->mso_pixel_overlap = 0; }
-u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid) +static u32 update_display_info(struct drm_connector *connector,
const struct drm_edid *drm_edid)
{ struct drm_display_info *info = &connector->display_info;
- const struct edid *edid = drm_edid->edid;
- u32 quirks = edid_get_quirks(edid);
u32 quirks = edid_get_quirks(drm_edid);
drm_reset_display_info(connector);
info->width_mm = edid->width_cm * 10; info->height_mm = edid->height_cm * 10;
- drm_get_monitor_range(connector, edid);
drm_get_monitor_range(connector, drm_edid);
if (edid->revision < 3) goto out;
@@ -5656,7 +5658,7 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi goto out;
info->color_formats |= DRM_COLOR_FORMAT_RGB444;
- drm_parse_cea_ext(connector, edid);
drm_parse_cea_ext(connector, drm_edid);
/*
- Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3?
@@ -5709,7 +5711,7 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
- drm_update_mso(connector, edid);
- drm_update_mso(connector, drm_edid);
out: if (quirks & EDID_QUIRK_NON_DESKTOP) { @@ -5721,6 +5723,16 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi return quirks; }
+u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid) +{
- struct drm_edid drm_edid = {
.edid = edid,
.size = edid_size(edid),
- };
- return update_display_info(connector, &drm_edid);
+}
static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *dev, struct displayid_detailed_timings_1 *timings, bool type_7) @@ -5833,7 +5845,7 @@ static int drm_edid_connector_update(struct drm_connector *connector, * To avoid multiple parsing of same block, lets parse that map * from sink info, before parsing CEA modes. */
- quirks = drm_add_display_info(connector, edid);
quirks = update_display_info(connector, drm_edid);
/* Depends on info->cea_rev set by drm_add_display_info() above */ drm_edid_to_eld(connector, edid);
On 5/6/2022 3:46 PM, Jani Nikula wrote:
On Fri, 06 May 2022, Jani Nikula jani.nikula@intel.com wrote:
We'll need to propagate drm_edid everywhere.
I seem to have copy-pasted a TAB in some of the commit messages, in a way that does not show up in git log.
Signed-off-by: Jani Nikula jani.nikula@intel.com
drivers/gpu/drm/drm_edid.c | 50 +++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 946296632b2e..c9d48fbd0a76 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2419,13 +2419,13 @@ EXPORT_SYMBOL(drm_edid_duplicate);
/**
- edid_get_quirks - return quirk flags for a given EDID
- @edid: EDID to process
*/
- @drm_edid: EDID to process
- This tells subsequent routines what fixes they need to apply.
-static u32 edid_get_quirks(const struct edid *edid) +static u32 edid_get_quirks(const struct drm_edid *drm_edid) {
- u32 panel_id = edid_extract_panel_id(edid);
- u32 panel_id = edid_extract_panel_id(drm_edid->edid); const struct edid_quirk *quirk; int i;
@@ -5448,7 +5448,7 @@ static void drm_parse_microsoft_vsdb(struct drm_connector *connector, }
static void drm_parse_cea_ext(struct drm_connector *connector,
const struct edid *edid)
{ struct drm_display_info *info = &connector->display_info; struct drm_edid_iter edid_iter;const struct drm_edid *drm_edid)
@@ -5456,7 +5456,7 @@ static void drm_parse_cea_ext(struct drm_connector *connector, struct cea_db_iter iter; const u8 *edid_ext;
- drm_edid_iter_begin(edid, &edid_iter);
- drm_edid_iter_begin(drm_edid->edid, &edid_iter); drm_edid_iter_for_each(edid_ext, &edid_iter) { if (edid_ext[0] != CEA_EXT) continue;
@@ -5477,7 +5477,7 @@ static void drm_parse_cea_ext(struct drm_connector *connector, } drm_edid_iter_end(&edid_iter);
- cea_db_iter_edid_begin(edid, &iter);
- cea_db_iter_edid_begin(drm_edid->edid, &iter); cea_db_iter_for_each(db, &iter) { /* FIXME: convert parsers to use struct cea_db */ const u8 *data = (const u8 *)db;
@@ -5523,16 +5523,15 @@ void get_monitor_range(const struct detailed_timing *timing, monitor_range->max_vfreq = range->max_vfreq; }
-static -void drm_get_monitor_range(struct drm_connector *connector,
const struct edid *edid)
+static void drm_get_monitor_range(struct drm_connector *connector,
{ struct drm_display_info *info = &connector->display_info;const struct drm_edid *drm_edid)
- if (!version_greater(edid, 1, 1))
- if (!version_greater(drm_edid->edid, 1, 1)) return;
- drm_for_each_detailed_block(edid, get_monitor_range,
drm_for_each_detailed_block(drm_edid->edid, get_monitor_range, &info->monitor_range);
DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n",
@@ -5592,12 +5591,13 @@ static void drm_parse_vesa_mso_data(struct drm_connector *connector, info->mso_stream_count, info->mso_pixel_overlap); }
-static void drm_update_mso(struct drm_connector *connector, const struct edid *edid) +static void drm_update_mso(struct drm_connector *connector,
{ const struct displayid_block *block; struct displayid_iter iter;const struct drm_edid *drm_edid)
- displayid_iter_edid_begin(edid, &iter);
- displayid_iter_edid_begin(drm_edid->edid, &iter); displayid_iter_for_each(block, &iter) { if (block->tag == DATA_BLOCK_2_VENDOR_SPECIFIC) drm_parse_vesa_mso_data(connector, block);
@@ -5636,18 +5636,20 @@ drm_reset_display_info(struct drm_connector *connector) info->mso_pixel_overlap = 0; }
-u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid) +static u32 update_display_info(struct drm_connector *connector,
{ struct drm_display_info *info = &connector->display_info;const struct drm_edid *drm_edid)
- const struct edid *edid = drm_edid->edid;
- u32 quirks = edid_get_quirks(edid);
u32 quirks = edid_get_quirks(drm_edid);
drm_reset_display_info(connector);
info->width_mm = edid->width_cm * 10; info->height_mm = edid->height_cm * 10;
- drm_get_monitor_range(connector, edid);
drm_get_monitor_range(connector, drm_edid);
if (edid->revision < 3) goto out;
@@ -5656,7 +5658,7 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi goto out;
info->color_formats |= DRM_COLOR_FORMAT_RGB444;
- drm_parse_cea_ext(connector, edid);
drm_parse_cea_ext(connector, drm_edid);
/*
- Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3?
@@ -5709,7 +5711,7 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
- drm_update_mso(connector, edid);
drm_update_mso(connector, drm_edid);
out: if (quirks & EDID_QUIRK_NON_DESKTOP) {
@@ -5721,6 +5723,16 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi return quirks; }
+u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid) +{
- struct drm_edid drm_edid = {
.edid = edid,
.size = edid_size(edid),
- };
- return update_display_info(connector, &drm_edid);
+}
- static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *dev, struct displayid_detailed_timings_1 *timings, bool type_7)
@@ -5833,7 +5845,7 @@ static int drm_edid_connector_update(struct drm_connector *connector, * To avoid multiple parsing of same block, lets parse that map * from sink info, before parsing CEA modes. */
- quirks = drm_add_display_info(connector, edid);
quirks = update_display_info(connector, drm_edid);
/* Depends on info->cea_rev set by drm_add_display_info() above */
Perhaps the comment above needs to be updated with update_display_info()
Patch looks good to me.
Reviewed-by: Ankit Nautiyal ankit.k.nautiyal@intel.com
drm_edid_to_eld(connector, edid);
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index c9d48fbd0a76..74038be72ad3 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -4865,13 +4865,13 @@ static void clear_eld(struct drm_connector *connector) /* * drm_edid_to_eld - build ELD from EDID * @connector: connector corresponding to the HDMI/DP sink - * @edid: EDID to parse + * @drm_edid: EDID to parse * * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. The * HDCP and Port_ID ELD fields are left for the graphics driver to fill in. */ static void drm_edid_to_eld(struct drm_connector *connector, - const struct edid *edid) + const struct drm_edid *drm_edid) { const struct drm_display_info *info = &connector->display_info; const struct cea_db *db; @@ -4882,10 +4882,10 @@ static void drm_edid_to_eld(struct drm_connector *connector,
clear_eld(connector);
- if (!edid) + if (!drm_edid) return;
- mnl = get_monitor_name(edid, &eld[DRM_ELD_MONITOR_NAME_STRING]); + mnl = get_monitor_name(drm_edid->edid, &eld[DRM_ELD_MONITOR_NAME_STRING]); DRM_DEBUG_KMS("ELD monitor %s\n", &eld[DRM_ELD_MONITOR_NAME_STRING]);
eld[DRM_ELD_CEA_EDID_VER_MNL] = info->cea_rev << DRM_ELD_CEA_EDID_VER_SHIFT; @@ -4893,12 +4893,12 @@ static void drm_edid_to_eld(struct drm_connector *connector,
eld[DRM_ELD_VER] = DRM_ELD_VER_CEA861D;
- eld[DRM_ELD_MANUFACTURER_NAME0] = edid->mfg_id[0]; - eld[DRM_ELD_MANUFACTURER_NAME1] = edid->mfg_id[1]; - eld[DRM_ELD_PRODUCT_CODE0] = edid->prod_code[0]; - eld[DRM_ELD_PRODUCT_CODE1] = edid->prod_code[1]; + eld[DRM_ELD_MANUFACTURER_NAME0] = drm_edid->edid->mfg_id[0]; + eld[DRM_ELD_MANUFACTURER_NAME1] = drm_edid->edid->mfg_id[1]; + eld[DRM_ELD_PRODUCT_CODE0] = drm_edid->edid->prod_code[0]; + eld[DRM_ELD_PRODUCT_CODE1] = drm_edid->edid->prod_code[1];
- cea_db_iter_edid_begin(edid, &iter); + cea_db_iter_edid_begin(drm_edid->edid, &iter); cea_db_iter_for_each(db, &iter) { const u8 *data = cea_db_data(db); int len = cea_db_payload_len(db); @@ -5848,7 +5848,7 @@ static int drm_edid_connector_update(struct drm_connector *connector, quirks = update_display_info(connector, drm_edid);
/* Depends on info->cea_rev set by drm_add_display_info() above */ - drm_edid_to_eld(connector, edid); + drm_edid_to_eld(connector, drm_edid);
/* * EDID spec says modes should be preferred in this order:
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 95 ++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 49 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 74038be72ad3..fdc6ad651d3f 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3235,16 +3235,16 @@ do_inferred_modes(const struct detailed_timing *timing, void *c) } }
-static int -add_inferred_modes(struct drm_connector *connector, const struct edid *edid) +static int add_inferred_modes(struct drm_connector *connector, + const struct drm_edid *drm_edid) { struct detailed_mode_closure closure = { .connector = connector, - .edid = edid, + .edid = drm_edid->edid, };
- if (version_greater(edid, 1, 0)) - drm_for_each_detailed_block(edid, do_inferred_modes, &closure); + if (version_greater(drm_edid->edid, 1, 0)) + drm_for_each_detailed_block(drm_edid->edid, do_inferred_modes, &closure);
return closure.modes; } @@ -3294,10 +3294,11 @@ do_established_modes(const struct detailed_timing *timing, void *c) * bitmap of the supported "established modes" list (defined above). Tease them * out and add them to the global modes list. */ -static int -add_established_modes(struct drm_connector *connector, const struct edid *edid) +static int add_established_modes(struct drm_connector *connector, + const struct drm_edid *drm_edid) { struct drm_device *dev = connector->dev; + const struct edid *edid = drm_edid->edid; unsigned long est_bits = edid->established_timings.t1 | (edid->established_timings.t2 << 8) | ((edid->established_timings.mfg_rsvd & 0x80) << 9); @@ -3320,7 +3321,7 @@ add_established_modes(struct drm_connector *connector, const struct edid *edid) }
if (version_greater(edid, 1, 0)) - drm_for_each_detailed_block(edid, do_established_modes, + drm_for_each_detailed_block(drm_edid->edid, do_established_modes, &closure);
return modes + closure.modes; @@ -3355,28 +3356,28 @@ do_standard_modes(const struct detailed_timing *timing, void *c) * using the appropriate standard (DMT, GTF, or CVT). Grab them from EDID and * add them to the list. */ -static int -add_standard_modes(struct drm_connector *connector, const struct edid *edid) +static int add_standard_modes(struct drm_connector *connector, + const struct drm_edid *drm_edid) { int i, modes = 0; struct detailed_mode_closure closure = { .connector = connector, - .edid = edid, + .edid = drm_edid->edid, };
for (i = 0; i < EDID_STD_TIMINGS; i++) { struct drm_display_mode *newmode;
- newmode = drm_mode_std(connector, edid, - &edid->standard_timings[i]); + newmode = drm_mode_std(connector, drm_edid->edid, + &drm_edid->edid->standard_timings[i]); if (newmode) { drm_mode_probed_add(connector, newmode); modes++; } }
- if (version_greater(edid, 1, 0)) - drm_for_each_detailed_block(edid, do_standard_modes, + if (version_greater(drm_edid->edid, 1, 0)) + drm_for_each_detailed_block(drm_edid->edid, do_standard_modes, &closure);
/* XXX should also look for standard codes in VTB blocks */ @@ -3448,15 +3449,15 @@ do_cvt_mode(const struct detailed_timing *timing, void *c) }
static int -add_cvt_modes(struct drm_connector *connector, const struct edid *edid) +add_cvt_modes(struct drm_connector *connector, const struct drm_edid *drm_edid) { struct detailed_mode_closure closure = { .connector = connector, - .edid = edid, + .edid = drm_edid->edid, };
- if (version_greater(edid, 1, 2)) - drm_for_each_detailed_block(edid, do_cvt_mode, &closure); + if (version_greater(drm_edid->edid, 1, 2)) + drm_for_each_detailed_block(drm_edid->edid, do_cvt_mode, &closure);
/* XXX should also look for CVT codes in VTB blocks */
@@ -3501,22 +3502,21 @@ do_detailed_mode(const struct detailed_timing *timing, void *c) * @edid: EDID block to scan * @quirks: quirks to apply */ -static int -add_detailed_modes(struct drm_connector *connector, const struct edid *edid, - u32 quirks) +static int add_detailed_modes(struct drm_connector *connector, + const struct drm_edid *drm_edid, u32 quirks) { struct detailed_mode_closure closure = { .connector = connector, - .edid = edid, + .edid = drm_edid->edid, .preferred = true, .quirks = quirks, };
- if (closure.preferred && !version_greater(edid, 1, 3)) + if (closure.preferred && !version_greater(drm_edid->edid, 1, 3)) closure.preferred = - (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING); + (drm_edid->edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING);
- drm_for_each_detailed_block(edid, do_detailed_mode, &closure); + drm_for_each_detailed_block(drm_edid->edid, do_detailed_mode, &closure);
return closure.modes; } @@ -3570,7 +3570,7 @@ const u8 *drm_find_edid_extension(const struct edid *edid, }
/* Return true if the EDID has a CTA extension or a DisplayID CTA data block */ -static bool drm_edid_has_cta_extension(const struct edid *edid) +static bool drm_edid_has_cta_extension(const struct drm_edid *drm_edid) { const struct displayid_block *block; struct displayid_iter iter; @@ -3578,11 +3578,11 @@ static bool drm_edid_has_cta_extension(const struct edid *edid) bool found = false;
/* Look for a top level CEA extension block */ - if (drm_find_edid_extension(edid, CEA_EXT, &ext_index)) + if (drm_find_edid_extension(drm_edid->edid, CEA_EXT, &ext_index)) return true;
/* CEA blocks can also be found embedded in a DisplayID block */ - displayid_iter_edid_begin(edid, &iter); + displayid_iter_edid_begin(drm_edid->edid, &iter); displayid_iter_for_each(block, &iter) { if (block->tag == DATA_BLOCK_CTA) { found = true; @@ -3856,8 +3856,8 @@ static bool drm_valid_hdmi_vic(u8 vic) return vic > 0 && vic < ARRAY_SIZE(edid_4k_modes); }
-static int -add_alternate_cea_modes(struct drm_connector *connector, const struct edid *edid) +static int add_alternate_cea_modes(struct drm_connector *connector, + const struct drm_edid *drm_edid) { struct drm_device *dev = connector->dev; struct drm_display_mode *mode, *tmp; @@ -3865,7 +3865,7 @@ add_alternate_cea_modes(struct drm_connector *connector, const struct edid *edid int modes = 0;
/* Don't add CTA modes if the CTA extension block is missing */ - if (!drm_edid_has_cta_extension(edid)) + if (!drm_edid_has_cta_extension(drm_edid)) return 0;
/* @@ -4648,14 +4648,14 @@ static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector, hdmi->y420_cmdb_map = map; }
-static int -add_cea_modes(struct drm_connector *connector, const struct edid *edid) +static int add_cea_modes(struct drm_connector *connector, + const struct drm_edid *drm_edid) { const struct cea_db *db; struct cea_db_iter iter; int modes = 0;
- cea_db_iter_edid_begin(edid, &iter); + cea_db_iter_edid_begin(drm_edid->edid, &iter); cea_db_iter_for_each(db, &iter) { const u8 *hdmi = NULL, *video = NULL; u8 hdmi_len = 0, video_len = 0; @@ -5808,13 +5808,13 @@ static int add_displayid_detailed_1_modes(struct drm_connector *connector, }
static int add_displayid_detailed_modes(struct drm_connector *connector, - const struct edid *edid) + const struct drm_edid *drm_edid) { const struct displayid_block *block; struct displayid_iter iter; int num_modes = 0;
- displayid_iter_edid_begin(edid, &iter); + displayid_iter_edid_begin(drm_edid->edid, &iter); displayid_iter_for_each(block, &iter) { if (block->tag == DATA_BLOCK_TYPE_1_DETAILED_TIMING || block->tag == DATA_BLOCK_2_TYPE_7_DETAILED_TIMING) @@ -5828,7 +5828,6 @@ static int add_displayid_detailed_modes(struct drm_connector *connector, static int drm_edid_connector_update(struct drm_connector *connector, const struct drm_edid *drm_edid) { - const struct edid *edid; int num_modes = 0; u32 quirks;
@@ -5838,8 +5837,6 @@ static int drm_edid_connector_update(struct drm_connector *connector, return 0; }
- edid = drm_edid->edid; - /* * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks. * To avoid multiple parsing of same block, lets parse that map @@ -5864,15 +5861,15 @@ static int drm_edid_connector_update(struct drm_connector *connector, * * XXX order for additional mode types in extension blocks? */ - num_modes += add_detailed_modes(connector, edid, quirks); - num_modes += add_cvt_modes(connector, edid); - num_modes += add_standard_modes(connector, edid); - num_modes += add_established_modes(connector, edid); - num_modes += add_cea_modes(connector, edid); - num_modes += add_alternate_cea_modes(connector, edid); - num_modes += add_displayid_detailed_modes(connector, edid); - if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) - num_modes += add_inferred_modes(connector, edid); + num_modes += add_detailed_modes(connector, drm_edid, quirks); + num_modes += add_cvt_modes(connector, drm_edid); + num_modes += add_standard_modes(connector, drm_edid); + num_modes += add_established_modes(connector, drm_edid); + num_modes += add_cea_modes(connector, drm_edid); + num_modes += add_alternate_cea_modes(connector, drm_edid); + num_modes += add_displayid_detailed_modes(connector, drm_edid); + if (drm_edid->edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) + num_modes += add_inferred_modes(connector, drm_edid);
if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) edid_fixup_preferred(connector, quirks);
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index fdc6ad651d3f..1abdd88ff64b 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -96,7 +96,7 @@ static int oui(u8 first, u8 second, u8 third)
struct detailed_mode_closure { struct drm_connector *connector; - const struct edid *edid; + const struct drm_edid *drm_edid; bool preferred; u32 quirks; int modes; @@ -3208,25 +3208,25 @@ do_inferred_modes(const struct detailed_timing *timing, void *c) return;
closure->modes += drm_dmt_modes_for_range(closure->connector, - closure->edid, + closure->drm_edid->edid, timing);
- if (!version_greater(closure->edid, 1, 1)) + if (!version_greater(closure->drm_edid->edid, 1, 1)) return; /* GTF not defined yet */
switch (range->flags) { case 0x02: /* secondary gtf, XXX could do more */ case 0x00: /* default gtf */ closure->modes += drm_gtf_modes_for_range(closure->connector, - closure->edid, + closure->drm_edid->edid, timing); break; case 0x04: /* cvt, only in 1.4+ */ - if (!version_greater(closure->edid, 1, 3)) + if (!version_greater(closure->drm_edid->edid, 1, 3)) break;
closure->modes += drm_cvt_modes_for_range(closure->connector, - closure->edid, + closure->drm_edid->edid, timing); break; case 0x01: /* just the ranges, no formula */ @@ -3240,7 +3240,7 @@ static int add_inferred_modes(struct drm_connector *connector, { struct detailed_mode_closure closure = { .connector = connector, - .edid = drm_edid->edid, + .drm_edid = drm_edid, };
if (version_greater(drm_edid->edid, 1, 0)) @@ -3305,7 +3305,7 @@ static int add_established_modes(struct drm_connector *connector, int i, modes = 0; struct detailed_mode_closure closure = { .connector = connector, - .edid = edid, + .drm_edid = drm_edid, };
for (i = 0; i <= EDID_EST_TIMINGS; i++) { @@ -3333,7 +3333,6 @@ do_standard_modes(const struct detailed_timing *timing, void *c) struct detailed_mode_closure *closure = c; const struct detailed_non_pixel *data = &timing->data.other_data; struct drm_connector *connector = closure->connector; - const struct edid *edid = closure->edid; int i;
if (!is_display_descriptor(timing, EDID_DETAIL_STD_MODES)) @@ -3343,7 +3342,7 @@ do_standard_modes(const struct detailed_timing *timing, void *c) const struct std_timing *std = &data->data.timings[i]; struct drm_display_mode *newmode;
- newmode = drm_mode_std(connector, edid, std); + newmode = drm_mode_std(connector, closure->drm_edid->edid, std); if (newmode) { drm_mode_probed_add(connector, newmode); closure->modes++; @@ -3362,7 +3361,7 @@ static int add_standard_modes(struct drm_connector *connector, int i, modes = 0; struct detailed_mode_closure closure = { .connector = connector, - .edid = drm_edid->edid, + .drm_edid = drm_edid, };
for (i = 0; i < EDID_STD_TIMINGS; i++) { @@ -3453,7 +3452,7 @@ add_cvt_modes(struct drm_connector *connector, const struct drm_edid *drm_edid) { struct detailed_mode_closure closure = { .connector = connector, - .edid = drm_edid->edid, + .drm_edid = drm_edid, };
if (version_greater(drm_edid->edid, 1, 2)) @@ -3476,7 +3475,7 @@ do_detailed_mode(const struct detailed_timing *timing, void *c) return;
newmode = drm_mode_detailed(closure->connector->dev, - closure->edid, timing, + closure->drm_edid->edid, timing, closure->quirks); if (!newmode) return; @@ -3507,7 +3506,7 @@ static int add_detailed_modes(struct drm_connector *connector, { struct detailed_mode_closure closure = { .connector = connector, - .edid = drm_edid->edid, + .drm_edid = drm_edid, .preferred = true, .quirks = quirks, };
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 1abdd88ff64b..b5d7347f32d9 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2910,7 +2910,7 @@ drm_mode_do_interlace_quirk(struct drm_display_mode *mode, * drm_display_mode. */ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, - const struct edid *edid, + const struct drm_edid *drm_edid, const struct detailed_timing *timing, u32 quirks) { @@ -2998,8 +2998,8 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, }
if (quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { - mode->width_mm = edid->width_cm * 10; - mode->height_mm = edid->height_cm * 10; + mode->width_mm = drm_edid->edid->width_cm * 10; + mode->height_mm = drm_edid->edid->height_cm * 10; }
mode->type = DRM_MODE_TYPE_DRIVER; @@ -3475,7 +3475,7 @@ do_detailed_mode(const struct detailed_timing *timing, void *c) return;
newmode = drm_mode_detailed(closure->connector->dev, - closure->drm_edid->edid, timing, + closure->drm_edid, timing, closure->quirks); if (!newmode) return;
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index b5d7347f32d9..88bb6c7ac97c 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3103,16 +3103,16 @@ static bool valid_inferred_mode(const struct drm_connector *connector, return ok; }
-static int -drm_dmt_modes_for_range(struct drm_connector *connector, const struct edid *edid, - const struct detailed_timing *timing) +static int drm_dmt_modes_for_range(struct drm_connector *connector, + const struct drm_edid *drm_edid, + const struct detailed_timing *timing) { int i, modes = 0; struct drm_display_mode *newmode; struct drm_device *dev = connector->dev;
for (i = 0; i < ARRAY_SIZE(drm_dmt_modes); i++) { - if (mode_in_range(drm_dmt_modes + i, edid, timing) && + if (mode_in_range(drm_dmt_modes + i, drm_edid->edid, timing) && valid_inferred_mode(connector, drm_dmt_modes + i)) { newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]); if (newmode) { @@ -3208,7 +3208,7 @@ do_inferred_modes(const struct detailed_timing *timing, void *c) return;
closure->modes += drm_dmt_modes_for_range(closure->connector, - closure->drm_edid->edid, + closure->drm_edid, timing);
if (!version_greater(closure->drm_edid->edid, 1, 1))
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 88bb6c7ac97c..3931c3318cf7 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3138,9 +3138,9 @@ void drm_mode_fixup_1366x768(struct drm_display_mode *mode) } }
-static int -drm_gtf_modes_for_range(struct drm_connector *connector, const struct edid *edid, - const struct detailed_timing *timing) +static int drm_gtf_modes_for_range(struct drm_connector *connector, + const struct drm_edid *drm_edid, + const struct detailed_timing *timing) { int i, modes = 0; struct drm_display_mode *newmode; @@ -3154,7 +3154,7 @@ drm_gtf_modes_for_range(struct drm_connector *connector, const struct edid *edid return modes;
drm_mode_fixup_1366x768(newmode); - if (!mode_in_range(newmode, edid, timing) || + if (!mode_in_range(newmode, drm_edid->edid, timing) || !valid_inferred_mode(connector, newmode)) { drm_mode_destroy(dev, newmode); continue; @@ -3218,7 +3218,7 @@ do_inferred_modes(const struct detailed_timing *timing, void *c) case 0x02: /* secondary gtf, XXX could do more */ case 0x00: /* default gtf */ closure->modes += drm_gtf_modes_for_range(closure->connector, - closure->drm_edid->edid, + closure->drm_edid, timing); break; case 0x04: /* cvt, only in 1.4+ */
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3931c3318cf7..27655da6ef9c 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3167,14 +3167,14 @@ static int drm_gtf_modes_for_range(struct drm_connector *connector, return modes; }
-static int -drm_cvt_modes_for_range(struct drm_connector *connector, const struct edid *edid, - const struct detailed_timing *timing) +static int drm_cvt_modes_for_range(struct drm_connector *connector, + const struct drm_edid *drm_edid, + const struct detailed_timing *timing) { int i, modes = 0; struct drm_display_mode *newmode; struct drm_device *dev = connector->dev; - bool rb = drm_monitor_supports_rb(edid); + bool rb = drm_monitor_supports_rb(drm_edid->edid);
for (i = 0; i < ARRAY_SIZE(extra_modes); i++) { const struct minimode *m = &extra_modes[i]; @@ -3184,7 +3184,7 @@ drm_cvt_modes_for_range(struct drm_connector *connector, const struct edid *edid return modes;
drm_mode_fixup_1366x768(newmode); - if (!mode_in_range(newmode, edid, timing) || + if (!mode_in_range(newmode, drm_edid->edid, timing) || !valid_inferred_mode(connector, newmode)) { drm_mode_destroy(dev, newmode); continue; @@ -3226,7 +3226,7 @@ do_inferred_modes(const struct detailed_timing *timing, void *c) break;
closure->modes += drm_cvt_modes_for_range(closure->connector, - closure->drm_edid->edid, + closure->drm_edid, timing); break; case 0x01: /* just the ranges, no formula */
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 52 ++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 25 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 27655da6ef9c..4b2d3453fc5c 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2655,11 +2655,11 @@ find_gtf2(const struct detailed_timing *descriptor, void *data)
/* Secondary GTF curve kicks in above some break frequency */ static int -drm_gtf2_hbreak(const struct edid *edid) +drm_gtf2_hbreak(const struct drm_edid *drm_edid) { const struct detailed_timing *descriptor = NULL;
- drm_for_each_detailed_block(edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(drm_edid->edid, find_gtf2, &descriptor);
BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.hfreq_start_khz) != 12);
@@ -2667,11 +2667,11 @@ drm_gtf2_hbreak(const struct edid *edid) }
static int -drm_gtf2_2c(const struct edid *edid) +drm_gtf2_2c(const struct drm_edid *drm_edid) { const struct detailed_timing *descriptor = NULL;
- drm_for_each_detailed_block(edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(drm_edid->edid, find_gtf2, &descriptor);
BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.c) != 13);
@@ -2679,11 +2679,11 @@ drm_gtf2_2c(const struct edid *edid) }
static int -drm_gtf2_m(const struct edid *edid) +drm_gtf2_m(const struct drm_edid *drm_edid) { const struct detailed_timing *descriptor = NULL;
- drm_for_each_detailed_block(edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(drm_edid->edid, find_gtf2, &descriptor);
BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.m) != 14);
@@ -2691,11 +2691,11 @@ drm_gtf2_m(const struct edid *edid) }
static int -drm_gtf2_k(const struct edid *edid) +drm_gtf2_k(const struct drm_edid *drm_edid) { const struct detailed_timing *descriptor = NULL;
- drm_for_each_detailed_block(edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(drm_edid->edid, find_gtf2, &descriptor);
BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.k) != 16);
@@ -2703,11 +2703,11 @@ drm_gtf2_k(const struct edid *edid) }
static int -drm_gtf2_2j(const struct edid *edid) +drm_gtf2_2j(const struct drm_edid *drm_edid) { const struct detailed_timing *descriptor = NULL;
- drm_for_each_detailed_block(edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(drm_edid->edid, find_gtf2, &descriptor);
BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.j) != 17);
@@ -2715,12 +2715,14 @@ drm_gtf2_2j(const struct edid *edid) }
/* Get standard timing level (CVT/GTF/DMT). */ -static int standard_timing_level(const struct edid *edid) +static int standard_timing_level(const struct drm_edid *drm_edid) { + const struct edid *edid = drm_edid->edid; + if (edid->revision >= 2) { if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)) return LEVEL_CVT; - if (drm_gtf2_hbreak(edid)) + if (drm_gtf2_hbreak(drm_edid)) return LEVEL_GTF2; if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) return LEVEL_GTF; @@ -2752,9 +2754,9 @@ static int drm_mode_hsync(const struct drm_display_mode *mode) * Take the standard timing params (in this case width, aspect, and refresh) * and convert them into a real mode using CVT/GTF/DMT. */ -static struct drm_display_mode * -drm_mode_std(struct drm_connector *connector, const struct edid *edid, - const struct std_timing *t) +static struct drm_display_mode *drm_mode_std(struct drm_connector *connector, + const struct drm_edid *drm_edid, + const struct std_timing *t) { struct drm_device *dev = connector->dev; struct drm_display_mode *m, *mode = NULL; @@ -2764,7 +2766,7 @@ drm_mode_std(struct drm_connector *connector, const struct edid *edid, >> EDID_TIMING_ASPECT_SHIFT; unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK) >> EDID_TIMING_VFREQ_SHIFT; - int timing_level = standard_timing_level(edid); + int timing_level = standard_timing_level(drm_edid);
if (bad_std_timing(t->hsize, t->vfreq_aspect)) return NULL; @@ -2775,7 +2777,7 @@ drm_mode_std(struct drm_connector *connector, const struct edid *edid, vrefresh_rate = vfreq + 60; /* the vdisplay is calculated based on the aspect ratio */ if (aspect_ratio == 0) { - if (edid->revision < 3) + if (drm_edid->edid->revision < 3) vsize = hsize; else vsize = (hsize * 10) / 16; @@ -2818,7 +2820,7 @@ drm_mode_std(struct drm_connector *connector, const struct edid *edid, }
/* check whether it can be found in default mode table */ - if (drm_monitor_supports_rb(edid)) { + if (drm_monitor_supports_rb(drm_edid->edid)) { mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate, true); if (mode) @@ -2844,14 +2846,14 @@ drm_mode_std(struct drm_connector *connector, const struct edid *edid, mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); if (!mode) return NULL; - if (drm_mode_hsync(mode) > drm_gtf2_hbreak(edid)) { + if (drm_mode_hsync(mode) > drm_gtf2_hbreak(drm_edid)) { drm_mode_destroy(dev, mode); mode = drm_gtf_mode_complex(dev, hsize, vsize, vrefresh_rate, 0, 0, - drm_gtf2_m(edid), - drm_gtf2_2c(edid), - drm_gtf2_k(edid), - drm_gtf2_2j(edid)); + drm_gtf2_m(drm_edid), + drm_gtf2_2c(drm_edid), + drm_gtf2_k(drm_edid), + drm_gtf2_2j(drm_edid)); } break; case LEVEL_CVT: @@ -3342,7 +3344,7 @@ do_standard_modes(const struct detailed_timing *timing, void *c) const struct std_timing *std = &data->data.timings[i]; struct drm_display_mode *newmode;
- newmode = drm_mode_std(connector, closure->drm_edid->edid, std); + newmode = drm_mode_std(connector, closure->drm_edid, std); if (newmode) { drm_mode_probed_add(connector, newmode); closure->modes++; @@ -3367,7 +3369,7 @@ static int add_standard_modes(struct drm_connector *connector, for (i = 0; i < EDID_STD_TIMINGS; i++) { struct drm_display_mode *newmode;
- newmode = drm_mode_std(connector, drm_edid->edid, + newmode = drm_mode_std(connector, drm_edid, &drm_edid->edid->standard_timings[i]); if (newmode) { drm_mode_probed_add(connector, newmode);
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 4b2d3453fc5c..b8deced8de01 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2627,16 +2627,16 @@ is_rb(const struct detailed_timing *descriptor, void *data)
/* EDID 1.4 defines this explicitly. For EDID 1.3, we guess, badly. */ static bool -drm_monitor_supports_rb(const struct edid *edid) +drm_monitor_supports_rb(const struct drm_edid *drm_edid) { - if (edid->revision >= 4) { + if (drm_edid->edid->revision >= 4) { bool ret = false;
- drm_for_each_detailed_block(edid, is_rb, &ret); + drm_for_each_detailed_block(drm_edid->edid, is_rb, &ret); return ret; }
- return ((edid->input & DRM_EDID_INPUT_DIGITAL) != 0); + return ((drm_edid->edid->input & DRM_EDID_INPUT_DIGITAL) != 0); }
static void @@ -2820,7 +2820,7 @@ static struct drm_display_mode *drm_mode_std(struct drm_connector *connector, }
/* check whether it can be found in default mode table */ - if (drm_monitor_supports_rb(drm_edid->edid)) { + if (drm_monitor_supports_rb(drm_edid)) { mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate, true); if (mode) @@ -3059,10 +3059,11 @@ range_pixel_clock(const struct edid *edid, const u8 *t) return t[9] * 10000 + 5001; }
-static bool -mode_in_range(const struct drm_display_mode *mode, const struct edid *edid, - const struct detailed_timing *timing) +static bool mode_in_range(const struct drm_display_mode *mode, + const struct drm_edid *drm_edid, + const struct detailed_timing *timing) { + const struct edid *edid = drm_edid->edid; u32 max_clock; const u8 *t = (const u8 *)timing;
@@ -3081,7 +3082,7 @@ mode_in_range(const struct drm_display_mode *mode, const struct edid *edid, if (t[13] && mode->hdisplay > 8 * (t[13] + (256 * (t[12]&0x3)))) return false;
- if (mode_is_rb(mode) && !drm_monitor_supports_rb(edid)) + if (mode_is_rb(mode) && !drm_monitor_supports_rb(drm_edid)) return false;
return true; @@ -3114,7 +3115,7 @@ static int drm_dmt_modes_for_range(struct drm_connector *connector, struct drm_device *dev = connector->dev;
for (i = 0; i < ARRAY_SIZE(drm_dmt_modes); i++) { - if (mode_in_range(drm_dmt_modes + i, drm_edid->edid, timing) && + if (mode_in_range(drm_dmt_modes + i, drm_edid, timing) && valid_inferred_mode(connector, drm_dmt_modes + i)) { newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]); if (newmode) { @@ -3156,7 +3157,7 @@ static int drm_gtf_modes_for_range(struct drm_connector *connector, return modes;
drm_mode_fixup_1366x768(newmode); - if (!mode_in_range(newmode, drm_edid->edid, timing) || + if (!mode_in_range(newmode, drm_edid, timing) || !valid_inferred_mode(connector, newmode)) { drm_mode_destroy(dev, newmode); continue; @@ -3176,7 +3177,7 @@ static int drm_cvt_modes_for_range(struct drm_connector *connector, int i, modes = 0; struct drm_display_mode *newmode; struct drm_device *dev = connector->dev; - bool rb = drm_monitor_supports_rb(drm_edid->edid); + bool rb = drm_monitor_supports_rb(drm_edid);
for (i = 0; i < ARRAY_SIZE(extra_modes); i++) { const struct minimode *m = &extra_modes[i]; @@ -3186,7 +3187,7 @@ static int drm_cvt_modes_for_range(struct drm_connector *connector, return modes;
drm_mode_fixup_1366x768(newmode); - if (!mode_in_range(newmode, drm_edid->edid, timing) || + if (!mode_in_range(newmode, drm_edid, timing) || !valid_inferred_mode(connector, newmode)) { drm_mode_destroy(dev, newmode); continue;
We'll need to propagate drm_edid everywhere.
v2: Drop incorrect NULL name check (Dan Carpenter)
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index b8deced8de01..4fd2ee976d39 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -4812,15 +4812,15 @@ monitor_name(const struct detailed_timing *timing, void *data) *res = timing->data.other_data.data.str.str; }
-static int get_monitor_name(const struct edid *edid, char name[13]) +static int get_monitor_name(const struct drm_edid *drm_edid, char name[13]) { const char *edid_name = NULL; int mnl;
- if (!edid || !name) + if (!drm_edid || !name) return 0;
- drm_for_each_detailed_block(edid, monitor_name, &edid_name); + drm_for_each_detailed_block(drm_edid->edid, monitor_name, &edid_name); for (mnl = 0; edid_name && mnl < 13; mnl++) { if (edid_name[mnl] == 0x0a) break; @@ -4840,14 +4840,22 @@ static int get_monitor_name(const struct edid *edid, char name[13]) */ void drm_edid_get_monitor_name(const struct edid *edid, char *name, int bufsize) { - int name_length; - char buf[13]; + int name_length = 0;
if (bufsize <= 0) return;
- name_length = min(get_monitor_name(edid, buf), bufsize - 1); - memcpy(name, buf, name_length); + if (edid) { + char buf[13]; + struct drm_edid drm_edid = { + .edid = edid, + .size = edid_size(edid), + }; + + name_length = min(get_monitor_name(&drm_edid, buf), bufsize - 1); + memcpy(name, buf, name_length); + } + name[name_length] = '\0'; } EXPORT_SYMBOL(drm_edid_get_monitor_name); @@ -4887,7 +4895,7 @@ static void drm_edid_to_eld(struct drm_connector *connector, if (!drm_edid) return;
- mnl = get_monitor_name(drm_edid->edid, &eld[DRM_ELD_MONITOR_NAME_STRING]); + mnl = get_monitor_name(drm_edid, &eld[DRM_ELD_MONITOR_NAME_STRING]); DRM_DEBUG_KMS("ELD monitor %s\n", &eld[DRM_ELD_MONITOR_NAME_STRING]);
eld[DRM_ELD_CEA_EDID_VER_MNL] = info->cea_rev << DRM_ELD_CEA_EDID_VER_SHIFT;
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 4fd2ee976d39..2017feecbe1c 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2580,20 +2580,20 @@ vtb_for_each_detailed_block(const u8 *ext, detailed_cb *cb, void *closure) cb((const struct detailed_timing *)(det_base + 18 * i), closure); }
-static void -drm_for_each_detailed_block(const struct edid *edid, detailed_cb *cb, void *closure) +static void drm_for_each_detailed_block(const struct drm_edid *drm_edid, + detailed_cb *cb, void *closure) { struct drm_edid_iter edid_iter; const u8 *ext; int i;
- if (edid == NULL) + if (!drm_edid) return;
for (i = 0; i < EDID_DETAILED_TIMINGS; i++) - cb(&(edid->detailed_timings[i]), closure); + cb(&(drm_edid->edid->detailed_timings[i]), closure);
- drm_edid_iter_begin(edid, &edid_iter); + drm_edid_iter_begin(drm_edid->edid, &edid_iter); drm_edid_iter_for_each(ext, &edid_iter) { switch (*ext) { case CEA_EXT: @@ -2632,7 +2632,7 @@ drm_monitor_supports_rb(const struct drm_edid *drm_edid) if (drm_edid->edid->revision >= 4) { bool ret = false;
- drm_for_each_detailed_block(drm_edid->edid, is_rb, &ret); + drm_for_each_detailed_block(drm_edid, is_rb, &ret); return ret; }
@@ -2659,7 +2659,7 @@ drm_gtf2_hbreak(const struct drm_edid *drm_edid) { const struct detailed_timing *descriptor = NULL;
- drm_for_each_detailed_block(drm_edid->edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(drm_edid, find_gtf2, &descriptor);
BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.hfreq_start_khz) != 12);
@@ -2671,7 +2671,7 @@ drm_gtf2_2c(const struct drm_edid *drm_edid) { const struct detailed_timing *descriptor = NULL;
- drm_for_each_detailed_block(drm_edid->edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(drm_edid, find_gtf2, &descriptor);
BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.c) != 13);
@@ -2683,7 +2683,7 @@ drm_gtf2_m(const struct drm_edid *drm_edid) { const struct detailed_timing *descriptor = NULL;
- drm_for_each_detailed_block(drm_edid->edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(drm_edid, find_gtf2, &descriptor);
BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.m) != 14);
@@ -2695,7 +2695,7 @@ drm_gtf2_k(const struct drm_edid *drm_edid) { const struct detailed_timing *descriptor = NULL;
- drm_for_each_detailed_block(drm_edid->edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(drm_edid, find_gtf2, &descriptor);
BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.k) != 16);
@@ -2707,7 +2707,7 @@ drm_gtf2_2j(const struct drm_edid *drm_edid) { const struct detailed_timing *descriptor = NULL;
- drm_for_each_detailed_block(drm_edid->edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(drm_edid, find_gtf2, &descriptor);
BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.j) != 17);
@@ -3247,7 +3247,7 @@ static int add_inferred_modes(struct drm_connector *connector, };
if (version_greater(drm_edid->edid, 1, 0)) - drm_for_each_detailed_block(drm_edid->edid, do_inferred_modes, &closure); + drm_for_each_detailed_block(drm_edid, do_inferred_modes, &closure);
return closure.modes; } @@ -3324,7 +3324,7 @@ static int add_established_modes(struct drm_connector *connector, }
if (version_greater(edid, 1, 0)) - drm_for_each_detailed_block(drm_edid->edid, do_established_modes, + drm_for_each_detailed_block(drm_edid, do_established_modes, &closure);
return modes + closure.modes; @@ -3379,7 +3379,7 @@ static int add_standard_modes(struct drm_connector *connector, }
if (version_greater(drm_edid->edid, 1, 0)) - drm_for_each_detailed_block(drm_edid->edid, do_standard_modes, + drm_for_each_detailed_block(drm_edid, do_standard_modes, &closure);
/* XXX should also look for standard codes in VTB blocks */ @@ -3459,7 +3459,7 @@ add_cvt_modes(struct drm_connector *connector, const struct drm_edid *drm_edid) };
if (version_greater(drm_edid->edid, 1, 2)) - drm_for_each_detailed_block(drm_edid->edid, do_cvt_mode, &closure); + drm_for_each_detailed_block(drm_edid, do_cvt_mode, &closure);
/* XXX should also look for CVT codes in VTB blocks */
@@ -3518,7 +3518,7 @@ static int add_detailed_modes(struct drm_connector *connector, closure.preferred = (drm_edid->edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING);
- drm_for_each_detailed_block(drm_edid->edid, do_detailed_mode, &closure); + drm_for_each_detailed_block(drm_edid, do_detailed_mode, &closure);
return closure.modes; } @@ -4820,7 +4820,7 @@ static int get_monitor_name(const struct drm_edid *drm_edid, char name[13]) if (!drm_edid || !name) return 0;
- drm_for_each_detailed_block(drm_edid->edid, monitor_name, &edid_name); + drm_for_each_detailed_block(drm_edid, monitor_name, &edid_name); for (mnl = 0; edid_name && mnl < 13; mnl++) { if (edid_name[mnl] == 0x0a) break; @@ -5541,7 +5541,7 @@ static void drm_get_monitor_range(struct drm_connector *connector, if (!version_greater(drm_edid->edid, 1, 1)) return;
- drm_for_each_detailed_block(drm_edid->edid, get_monitor_range, + drm_for_each_detailed_block(drm_edid, get_monitor_range, &info->monitor_range);
DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n",
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 2017feecbe1c..52ea187394dd 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -4954,24 +4954,14 @@ static void drm_edid_to_eld(struct drm_connector *connector, drm_eld_size(eld), total_sad_count); }
-/** - * drm_edid_to_sad - extracts SADs from EDID - * @edid: EDID to parse - * @sads: pointer that will be set to the extracted SADs - * - * Looks for CEA EDID block and extracts SADs (Short Audio Descriptors) from it. - * - * Note: The returned pointer needs to be freed using kfree(). - * - * Return: The number of found SADs or negative number on error. - */ -int drm_edid_to_sad(const struct edid *edid, struct cea_sad **sads) +static int _drm_edid_to_sad(const struct drm_edid *drm_edid, + struct cea_sad **sads) { const struct cea_db *db; struct cea_db_iter iter; int count = 0;
- cea_db_iter_edid_begin(edid, &iter); + cea_db_iter_edid_begin(drm_edid->edid, &iter); cea_db_iter_for_each(db, &iter) { if (cea_db_tag(db) == CTA_DB_AUDIO) { int j; @@ -4997,6 +4987,27 @@ int drm_edid_to_sad(const struct edid *edid, struct cea_sad **sads)
return count; } + +/** + * drm_edid_to_sad - extracts SADs from EDID + * @edid: EDID to parse + * @sads: pointer that will be set to the extracted SADs + * + * Looks for CEA EDID block and extracts SADs (Short Audio Descriptors) from it. + * + * Note: The returned pointer needs to be freed using kfree(). + * + * Return: The number of found SADs or negative number on error. + */ +int drm_edid_to_sad(const struct edid *edid, struct cea_sad **sads) +{ + struct drm_edid drm_edid = { + .edid = edid, + .size = edid_size(edid), + }; + + return _drm_edid_to_sad(&drm_edid, sads); +} EXPORT_SYMBOL(drm_edid_to_sad);
/**
On Fri, May 06, 2022 at 01:10:24PM +0300, Jani Nikula wrote:
+int drm_edid_to_sad(const struct edid *edid, struct cea_sad **sads) +{
- struct drm_edid drm_edid = {
.edid = edid,
.size = edid_size(edid),
- };
- return _drm_edid_to_sad(&drm_edid, sads);
No need to check for NULL edid in these wrappers?
+} EXPORT_SYMBOL(drm_edid_to_sad);
/**
2.30.2
On Fri, 06 May 2022, Ville Syrjälä ville.syrjala@linux.intel.com wrote:
On Fri, May 06, 2022 at 01:10:24PM +0300, Jani Nikula wrote:
+int drm_edid_to_sad(const struct edid *edid, struct cea_sad **sads) +{
- struct drm_edid drm_edid = {
.edid = edid,
.size = edid_size(edid),
- };
- return _drm_edid_to_sad(&drm_edid, sads);
No need to check for NULL edid in these wrappers?
Yeah, we do, and CI concurs. *facepalm*.
BR, Jani.
+} EXPORT_SYMBOL(drm_edid_to_sad);
/**
2.30.2
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 39 ++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 52ea187394dd..51aee048bcff 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -5010,25 +5010,14 @@ int drm_edid_to_sad(const struct edid *edid, struct cea_sad **sads) } EXPORT_SYMBOL(drm_edid_to_sad);
-/** - * drm_edid_to_speaker_allocation - extracts Speaker Allocation Data Blocks from EDID - * @edid: EDID to parse - * @sadb: pointer to the speaker block - * - * Looks for CEA EDID block and extracts the Speaker Allocation Data Block from it. - * - * Note: The returned pointer needs to be freed using kfree(). - * - * Return: The number of found Speaker Allocation Blocks or negative number on - * error. - */ -int drm_edid_to_speaker_allocation(const struct edid *edid, u8 **sadb) +static int _drm_edid_to_speaker_allocation(const struct drm_edid *drm_edid, + u8 **sadb) { const struct cea_db *db; struct cea_db_iter iter; int count = 0;
- cea_db_iter_edid_begin(edid, &iter); + cea_db_iter_edid_begin(drm_edid->edid, &iter); cea_db_iter_for_each(db, &iter) { if (cea_db_tag(db) == CTA_DB_SPEAKER && cea_db_payload_len(db) == 3) { @@ -5046,6 +5035,28 @@ int drm_edid_to_speaker_allocation(const struct edid *edid, u8 **sadb)
return count; } + +/** + * drm_edid_to_speaker_allocation - extracts Speaker Allocation Data Blocks from EDID + * @edid: EDID to parse + * @sadb: pointer to the speaker block + * + * Looks for CEA EDID block and extracts the Speaker Allocation Data Block from it. + * + * Note: The returned pointer needs to be freed using kfree(). + * + * Return: The number of found Speaker Allocation Blocks or negative number on + * error. + */ +int drm_edid_to_speaker_allocation(const struct edid *edid, u8 **sadb) +{ + struct drm_edid drm_edid = { + .edid = edid, + .size = edid_size(edid), + }; + + return _drm_edid_to_speaker_allocation(&drm_edid, sadb); +} EXPORT_SYMBOL(drm_edid_to_speaker_allocation);
/**
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 51aee048bcff..3277b4fd33ce 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -5100,18 +5100,7 @@ int drm_av_sync_delay(struct drm_connector *connector, } EXPORT_SYMBOL(drm_av_sync_delay);
-/** - * drm_detect_hdmi_monitor - detect whether monitor is HDMI - * @edid: monitor EDID information - * - * Parse the CEA extension according to CEA-861-B. - * - * Drivers that have added the modes parsed from EDID to drm_display_info - * should use &drm_display_info.is_hdmi instead of calling this function. - * - * Return: True if the monitor is HDMI, false if not or unknown. - */ -bool drm_detect_hdmi_monitor(const struct edid *edid) +static bool _drm_detect_hdmi_monitor(const struct drm_edid *drm_edid) { const struct cea_db *db; struct cea_db_iter iter; @@ -5121,7 +5110,7 @@ bool drm_detect_hdmi_monitor(const struct edid *edid) * Because HDMI identifier is in Vendor Specific Block, * search it from all data blocks of CEA extension. */ - cea_db_iter_edid_begin(edid, &iter); + cea_db_iter_edid_begin(drm_edid->edid, &iter); cea_db_iter_for_each(db, &iter) { if (cea_db_is_hdmi_vsdb(db)) { hdmi = true; @@ -5132,6 +5121,27 @@ bool drm_detect_hdmi_monitor(const struct edid *edid)
return hdmi; } + +/** + * drm_detect_hdmi_monitor - detect whether monitor is HDMI + * @edid: monitor EDID information + * + * Parse the CEA extension according to CEA-861-B. + * + * Drivers that have added the modes parsed from EDID to drm_display_info + * should use &drm_display_info.is_hdmi instead of calling this function. + * + * Return: True if the monitor is HDMI, false if not or unknown. + */ +bool drm_detect_hdmi_monitor(const struct edid *edid) +{ + struct drm_edid drm_edid = { + .edid = edid, + .size = edid_size(edid), + }; + + return _drm_detect_hdmi_monitor(&drm_edid); +} EXPORT_SYMBOL(drm_detect_hdmi_monitor);
/**
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 40 ++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3277b4fd33ce..706552ae00ea 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -5144,19 +5144,7 @@ bool drm_detect_hdmi_monitor(const struct edid *edid) } EXPORT_SYMBOL(drm_detect_hdmi_monitor);
-/** - * drm_detect_monitor_audio - check monitor audio capability - * @edid: EDID block to scan - * - * Monitor should have CEA extension block. - * If monitor has 'basic audio', but no CEA audio blocks, it's 'basic - * audio' only. If there is any audio extension block and supported - * audio format, assume at least 'basic audio' support, even if 'basic - * audio' is not defined in EDID. - * - * Return: True if the monitor supports audio, false otherwise. - */ -bool drm_detect_monitor_audio(const struct edid *edid) +static bool _drm_detect_monitor_audio(const struct drm_edid *drm_edid) { struct drm_edid_iter edid_iter; const struct cea_db *db; @@ -5164,7 +5152,7 @@ bool drm_detect_monitor_audio(const struct edid *edid) const u8 *edid_ext; bool has_audio = false;
- drm_edid_iter_begin(edid, &edid_iter); + drm_edid_iter_begin(drm_edid->edid, &edid_iter); drm_edid_iter_for_each(edid_ext, &edid_iter) { if (edid_ext[0] == CEA_EXT) { has_audio = edid_ext[3] & EDID_BASIC_AUDIO; @@ -5179,7 +5167,7 @@ bool drm_detect_monitor_audio(const struct edid *edid) goto end; }
- cea_db_iter_edid_begin(edid, &iter); + cea_db_iter_edid_begin(drm_edid->edid, &iter); cea_db_iter_for_each(db, &iter) { if (cea_db_tag(db) == CTA_DB_AUDIO) { const u8 *data = cea_db_data(db); @@ -5197,6 +5185,28 @@ bool drm_detect_monitor_audio(const struct edid *edid) end: return has_audio; } + +/** + * drm_detect_monitor_audio - check monitor audio capability + * @edid: EDID block to scan + * + * Monitor should have CEA extension block. + * If monitor has 'basic audio', but no CEA audio blocks, it's 'basic + * audio' only. If there is any audio extension block and supported + * audio format, assume at least 'basic audio' support, even if 'basic + * audio' is not defined in EDID. + * + * Return: True if the monitor supports audio, false otherwise. + */ +bool drm_detect_monitor_audio(const struct edid *edid) +{ + struct drm_edid drm_edid = { + .edid = edid, + .size = edid_size(edid), + }; + + return _drm_detect_monitor_audio(&drm_edid); +} EXPORT_SYMBOL(drm_detect_monitor_audio);
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 706552ae00ea..82a242a71ecf 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -4430,12 +4430,13 @@ static bool cea_db_is_vendor(const struct cea_db *db, int vendor_oui) oui(data[2], data[1], data[0]) == vendor_oui; }
-static void cea_db_iter_edid_begin(const struct edid *edid, struct cea_db_iter *iter) +static void cea_db_iter_edid_begin(const struct drm_edid *drm_edid, + struct cea_db_iter *iter) { memset(iter, 0, sizeof(*iter));
- drm_edid_iter_begin(edid, &iter->edid_iter); - displayid_iter_edid_begin(edid, &iter->displayid_iter); + drm_edid_iter_begin(drm_edid->edid, &iter->edid_iter); + displayid_iter_edid_begin(drm_edid->edid, &iter->displayid_iter); }
static const struct cea_db * @@ -4657,7 +4658,7 @@ static int add_cea_modes(struct drm_connector *connector, struct cea_db_iter iter; int modes = 0;
- cea_db_iter_edid_begin(drm_edid->edid, &iter); + cea_db_iter_edid_begin(drm_edid, &iter); cea_db_iter_for_each(db, &iter) { const u8 *hdmi = NULL, *video = NULL; u8 hdmi_len = 0, video_len = 0; @@ -4908,7 +4909,7 @@ static void drm_edid_to_eld(struct drm_connector *connector, eld[DRM_ELD_PRODUCT_CODE0] = drm_edid->edid->prod_code[0]; eld[DRM_ELD_PRODUCT_CODE1] = drm_edid->edid->prod_code[1];
- cea_db_iter_edid_begin(drm_edid->edid, &iter); + cea_db_iter_edid_begin(drm_edid, &iter); cea_db_iter_for_each(db, &iter) { const u8 *data = cea_db_data(db); int len = cea_db_payload_len(db); @@ -4961,7 +4962,7 @@ static int _drm_edid_to_sad(const struct drm_edid *drm_edid, struct cea_db_iter iter; int count = 0;
- cea_db_iter_edid_begin(drm_edid->edid, &iter); + cea_db_iter_edid_begin(drm_edid, &iter); cea_db_iter_for_each(db, &iter) { if (cea_db_tag(db) == CTA_DB_AUDIO) { int j; @@ -5017,7 +5018,7 @@ static int _drm_edid_to_speaker_allocation(const struct drm_edid *drm_edid, struct cea_db_iter iter; int count = 0;
- cea_db_iter_edid_begin(drm_edid->edid, &iter); + cea_db_iter_edid_begin(drm_edid, &iter); cea_db_iter_for_each(db, &iter) { if (cea_db_tag(db) == CTA_DB_SPEAKER && cea_db_payload_len(db) == 3) { @@ -5110,7 +5111,7 @@ static bool _drm_detect_hdmi_monitor(const struct drm_edid *drm_edid) * Because HDMI identifier is in Vendor Specific Block, * search it from all data blocks of CEA extension. */ - cea_db_iter_edid_begin(drm_edid->edid, &iter); + cea_db_iter_edid_begin(drm_edid, &iter); cea_db_iter_for_each(db, &iter) { if (cea_db_is_hdmi_vsdb(db)) { hdmi = true; @@ -5167,7 +5168,7 @@ static bool _drm_detect_monitor_audio(const struct drm_edid *drm_edid) goto end; }
- cea_db_iter_edid_begin(drm_edid->edid, &iter); + cea_db_iter_edid_begin(drm_edid, &iter); cea_db_iter_for_each(db, &iter) { if (cea_db_tag(db) == CTA_DB_AUDIO) { const u8 *data = cea_db_data(db); @@ -5529,7 +5530,7 @@ static void drm_parse_cea_ext(struct drm_connector *connector, } drm_edid_iter_end(&edid_iter);
- cea_db_iter_edid_begin(drm_edid->edid, &iter); + cea_db_iter_edid_begin(drm_edid, &iter); cea_db_iter_for_each(db, &iter) { /* FIXME: convert parsers to use struct cea_db */ const u8 *data = (const u8 *)db;
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 82a242a71ecf..b453bbf2f642 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1614,36 +1614,36 @@ static const void *edid_extension_block_data(const struct edid *edid, int index) * struct drm_edid_iter iter; * const u8 *block; * - * drm_edid_iter_begin(edid, &iter); + * drm_edid_iter_begin(drm_edid, &iter); * drm_edid_iter_for_each(block, &iter) { * // do stuff with block * } * drm_edid_iter_end(&iter); */ struct drm_edid_iter { - const struct edid *edid; + const struct drm_edid *drm_edid;
/* Current block index. */ int index; };
-static void drm_edid_iter_begin(const struct edid *edid, +static void drm_edid_iter_begin(const struct drm_edid *drm_edid, struct drm_edid_iter *iter) { memset(iter, 0, sizeof(*iter));
- iter->edid = edid; + iter->drm_edid = drm_edid; }
static const void *__drm_edid_iter_next(struct drm_edid_iter *iter) { const void *block = NULL;
- if (!iter->edid) + if (!iter->drm_edid) return NULL;
- if (iter->index < edid_block_count(iter->edid)) - block = edid_block_data(iter->edid, iter->index++); + if (iter->index < edid_block_count(iter->drm_edid->edid)) + block = edid_block_data(iter->drm_edid->edid, iter->index++);
return block; } @@ -2593,7 +2593,7 @@ static void drm_for_each_detailed_block(const struct drm_edid *drm_edid, for (i = 0; i < EDID_DETAILED_TIMINGS; i++) cb(&(drm_edid->edid->detailed_timings[i]), closure);
- drm_edid_iter_begin(drm_edid->edid, &edid_iter); + drm_edid_iter_begin(drm_edid, &edid_iter); drm_edid_iter_for_each(ext, &edid_iter) { switch (*ext) { case CEA_EXT: @@ -4435,7 +4435,7 @@ static void cea_db_iter_edid_begin(const struct drm_edid *drm_edid, { memset(iter, 0, sizeof(*iter));
- drm_edid_iter_begin(drm_edid->edid, &iter->edid_iter); + drm_edid_iter_begin(drm_edid, &iter->edid_iter); displayid_iter_edid_begin(drm_edid->edid, &iter->displayid_iter); }
@@ -5153,7 +5153,7 @@ static bool _drm_detect_monitor_audio(const struct drm_edid *drm_edid) const u8 *edid_ext; bool has_audio = false;
- drm_edid_iter_begin(drm_edid->edid, &edid_iter); + drm_edid_iter_begin(drm_edid, &edid_iter); drm_edid_iter_for_each(edid_ext, &edid_iter) { if (edid_ext[0] == CEA_EXT) { has_audio = edid_ext[3] & EDID_BASIC_AUDIO; @@ -5509,7 +5509,7 @@ static void drm_parse_cea_ext(struct drm_connector *connector, struct cea_db_iter iter; const u8 *edid_ext;
- drm_edid_iter_begin(drm_edid->edid, &edid_iter); + drm_edid_iter_begin(drm_edid, &edid_iter); drm_edid_iter_for_each(edid_ext, &edid_iter) { if (edid_ext[0] != CEA_EXT) continue;
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index b453bbf2f642..82db7afb4f8e 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -6363,15 +6363,15 @@ static void drm_parse_tiled_block(struct drm_connector *connector, } }
-void drm_update_tile_info(struct drm_connector *connector, - const struct edid *edid) +static void _drm_update_tile_info(struct drm_connector *connector, + const struct drm_edid *drm_edid) { const struct displayid_block *block; struct displayid_iter iter;
connector->has_tile = false;
- displayid_iter_edid_begin(edid, &iter); + displayid_iter_edid_begin(drm_edid ? drm_edid->edid : NULL, &iter); displayid_iter_for_each(block, &iter) { if (block->tag == DATA_BLOCK_TILED_DISPLAY) drm_parse_tiled_block(connector, block); @@ -6383,3 +6383,14 @@ void drm_update_tile_info(struct drm_connector *connector, connector->tile_group = NULL; } } + +void drm_update_tile_info(struct drm_connector *connector, + const struct edid *edid) +{ + struct drm_edid drm_edid = { + .edid = edid, + .size = edid_size(edid), + }; + + _drm_update_tile_info(connector, &drm_edid); +}
We'll need to propagate drm_edid everywhere.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_displayid.c | 16 ++++++++-------- drivers/gpu/drm/drm_edid.c | 17 ++++++++++------- include/drm/drm_displayid.h | 6 +++--- include/drm/drm_edid.h | 6 ++++-- 4 files changed, 25 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/drm_displayid.c b/drivers/gpu/drm/drm_displayid.c index 32da557b960f..38ea8203df45 100644 --- a/drivers/gpu/drm/drm_displayid.c +++ b/drivers/gpu/drm/drm_displayid.c @@ -33,11 +33,11 @@ static int validate_displayid(const u8 *displayid, int length, int idx) return 0; }
-static const u8 *drm_find_displayid_extension(const struct edid *edid, +static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid, int *length, int *idx, int *ext_index) { - const u8 *displayid = drm_find_edid_extension(edid, DISPLAYID_EXT, ext_index); + const u8 *displayid = drm_find_edid_extension(drm_edid, DISPLAYID_EXT, ext_index); const struct displayid_header *base; int ret;
@@ -58,12 +58,12 @@ static const u8 *drm_find_displayid_extension(const struct edid *edid, return displayid; }
-void displayid_iter_edid_begin(const struct edid *edid, +void displayid_iter_edid_begin(const struct drm_edid *drm_edid, struct displayid_iter *iter) { memset(iter, 0, sizeof(*iter));
- iter->edid = edid; + iter->drm_edid = drm_edid; }
static const struct displayid_block * @@ -88,7 +88,7 @@ __displayid_iter_next(struct displayid_iter *iter) { const struct displayid_block *block;
- if (!iter->edid) + if (!iter->drm_edid) return NULL;
if (iter->section) { @@ -96,7 +96,7 @@ __displayid_iter_next(struct displayid_iter *iter) block = displayid_iter_block(iter); if (WARN_ON(!block)) { iter->section = NULL; - iter->edid = NULL; + iter->drm_edid = NULL; return NULL; }
@@ -109,12 +109,12 @@ __displayid_iter_next(struct displayid_iter *iter) }
for (;;) { - iter->section = drm_find_displayid_extension(iter->edid, + iter->section = drm_find_displayid_extension(iter->drm_edid, &iter->length, &iter->idx, &iter->ext_index); if (!iter->section) { - iter->edid = NULL; + iter->drm_edid = NULL; return NULL; }
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 82db7afb4f8e..bc64837ad706 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3545,10 +3545,13 @@ static int add_detailed_modes(struct drm_connector *connector,
/* * Search EDID for CEA extension block. + * + * FIXME: Prefer not returning pointers to raw EDID data. */ -const u8 *drm_find_edid_extension(const struct edid *edid, +const u8 *drm_find_edid_extension(const struct drm_edid *drm_edid, int ext_id, int *ext_index) { + const struct edid *edid = drm_edid ? drm_edid->edid : NULL; const u8 *edid_ext = NULL; int i;
@@ -3580,11 +3583,11 @@ static bool drm_edid_has_cta_extension(const struct drm_edid *drm_edid) bool found = false;
/* Look for a top level CEA extension block */ - if (drm_find_edid_extension(drm_edid->edid, CEA_EXT, &ext_index)) + if (drm_find_edid_extension(drm_edid, CEA_EXT, &ext_index)) return true;
/* CEA blocks can also be found embedded in a DisplayID block */ - displayid_iter_edid_begin(drm_edid->edid, &iter); + displayid_iter_edid_begin(drm_edid, &iter); displayid_iter_for_each(block, &iter) { if (block->tag == DATA_BLOCK_CTA) { found = true; @@ -4436,7 +4439,7 @@ static void cea_db_iter_edid_begin(const struct drm_edid *drm_edid, memset(iter, 0, sizeof(*iter));
drm_edid_iter_begin(drm_edid, &iter->edid_iter); - displayid_iter_edid_begin(drm_edid->edid, &iter->displayid_iter); + displayid_iter_edid_begin(drm_edid, &iter->displayid_iter); }
static const struct cea_db * @@ -5650,7 +5653,7 @@ static void drm_update_mso(struct drm_connector *connector, const struct displayid_block *block; struct displayid_iter iter;
- displayid_iter_edid_begin(drm_edid->edid, &iter); + displayid_iter_edid_begin(drm_edid, &iter); displayid_iter_for_each(block, &iter) { if (block->tag == DATA_BLOCK_2_VENDOR_SPECIFIC) drm_parse_vesa_mso_data(connector, block); @@ -5867,7 +5870,7 @@ static int add_displayid_detailed_modes(struct drm_connector *connector, struct displayid_iter iter; int num_modes = 0;
- displayid_iter_edid_begin(drm_edid->edid, &iter); + displayid_iter_edid_begin(drm_edid, &iter); displayid_iter_for_each(block, &iter) { if (block->tag == DATA_BLOCK_TYPE_1_DETAILED_TIMING || block->tag == DATA_BLOCK_2_TYPE_7_DETAILED_TIMING) @@ -6371,7 +6374,7 @@ static void _drm_update_tile_info(struct drm_connector *connector,
connector->has_tile = false;
- displayid_iter_edid_begin(drm_edid ? drm_edid->edid : NULL, &iter); + displayid_iter_edid_begin(drm_edid, &iter); displayid_iter_for_each(block, &iter) { if (block->tag == DATA_BLOCK_TILED_DISPLAY) drm_parse_tiled_block(connector, block); diff --git a/include/drm/drm_displayid.h b/include/drm/drm_displayid.h index 7ffbd9f7bfc7..49649eb8447e 100644 --- a/include/drm/drm_displayid.h +++ b/include/drm/drm_displayid.h @@ -25,7 +25,7 @@ #include <linux/types.h> #include <linux/bits.h>
-struct edid; +struct drm_edid;
#define VESA_IEEE_OUI 0x3a0292
@@ -141,7 +141,7 @@ struct displayid_vesa_vendor_specific_block {
/* DisplayID iteration */ struct displayid_iter { - const struct edid *edid; + const struct drm_edid *drm_edid;
const u8 *section; int length; @@ -149,7 +149,7 @@ struct displayid_iter { int ext_index; };
-void displayid_iter_edid_begin(const struct edid *edid, +void displayid_iter_edid_begin(const struct drm_edid *drm_edid, struct displayid_iter *iter); const struct displayid_block * __displayid_iter_next(struct displayid_iter *iter); diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index c3204a58fb09..c61e75ab8f63 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -28,6 +28,7 @@ #include <drm/drm_mode.h>
struct drm_device; +struct drm_edid; struct i2c_adapter;
#define EDID_LENGTH 128 @@ -578,8 +579,9 @@ struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, struct drm_display_mode * drm_display_mode_from_cea_vic(struct drm_device *dev, u8 video_code); -const u8 *drm_find_edid_extension(const struct edid *edid, - int ext_id, int *ext_index);
+/* Interface based on struct drm_edid */ +const u8 *drm_find_edid_extension(const struct drm_edid *drm_edid, + int ext_id, int *ext_index);
#endif /* __DRM_EDID_H__ */
We'll need to propagate drm_edid everywhere. Also make version_greater() a function for type safety.
Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index bc64837ad706..df48189ba2c7 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -45,10 +45,6 @@
#include "drm_crtc_internal.h"
-#define version_greater(edid, maj, min) \ - (((edid)->version > (maj)) || \ - ((edid)->version == (maj) && (edid)->revision > (min))) - static int oui(u8 first, u8 second, u8 third) { return (first << 16) | (second << 8) | third; @@ -1576,6 +1572,15 @@ struct drm_edid { const struct edid *edid; };
+static bool version_greater(const struct drm_edid *drm_edid, + u8 version, u8 revision) +{ + const struct edid *edid = drm_edid->edid; + + return edid->version > version || + (edid->version == version && edid->revision > revision); +} + static int edid_extension_block_count(const struct edid *edid) { return edid->extensions; @@ -3214,7 +3219,7 @@ do_inferred_modes(const struct detailed_timing *timing, void *c) closure->drm_edid, timing);
- if (!version_greater(closure->drm_edid->edid, 1, 1)) + if (!version_greater(closure->drm_edid, 1, 1)) return; /* GTF not defined yet */
switch (range->flags) { @@ -3225,7 +3230,7 @@ do_inferred_modes(const struct detailed_timing *timing, void *c) timing); break; case 0x04: /* cvt, only in 1.4+ */ - if (!version_greater(closure->drm_edid->edid, 1, 3)) + if (!version_greater(closure->drm_edid, 1, 3)) break;
closure->modes += drm_cvt_modes_for_range(closure->connector, @@ -3246,7 +3251,7 @@ static int add_inferred_modes(struct drm_connector *connector, .drm_edid = drm_edid, };
- if (version_greater(drm_edid->edid, 1, 0)) + if (version_greater(drm_edid, 1, 0)) drm_for_each_detailed_block(drm_edid, do_inferred_modes, &closure);
return closure.modes; @@ -3323,7 +3328,7 @@ static int add_established_modes(struct drm_connector *connector, } }
- if (version_greater(edid, 1, 0)) + if (version_greater(drm_edid, 1, 0)) drm_for_each_detailed_block(drm_edid, do_established_modes, &closure);
@@ -3378,7 +3383,7 @@ static int add_standard_modes(struct drm_connector *connector, } }
- if (version_greater(drm_edid->edid, 1, 0)) + if (version_greater(drm_edid, 1, 0)) drm_for_each_detailed_block(drm_edid, do_standard_modes, &closure);
@@ -3458,7 +3463,7 @@ add_cvt_modes(struct drm_connector *connector, const struct drm_edid *drm_edid) .drm_edid = drm_edid, };
- if (version_greater(drm_edid->edid, 1, 2)) + if (version_greater(drm_edid, 1, 2)) drm_for_each_detailed_block(drm_edid, do_cvt_mode, &closure);
/* XXX should also look for CVT codes in VTB blocks */ @@ -3514,7 +3519,7 @@ static int add_detailed_modes(struct drm_connector *connector, .quirks = quirks, };
- if (closure.preferred && !version_greater(drm_edid->edid, 1, 3)) + if (closure.preferred && !version_greater(drm_edid, 1, 3)) closure.preferred = (drm_edid->edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING);
@@ -5584,7 +5589,7 @@ static void drm_get_monitor_range(struct drm_connector *connector, { struct drm_display_info *info = &connector->display_info;
- if (!version_greater(drm_edid->edid, 1, 1)) + if (!version_greater(drm_edid, 1, 1)) return;
drm_for_each_detailed_block(drm_edid, get_monitor_range,
dri-devel@lists.freedesktop.org