diff options
author | Jani Nikula <jani.nikula@intel.com> | 2022-04-11 16:00:35 +0200 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2022-04-14 15:52:01 +0200 |
commit | f1e4c916f97f6adc0848515d269b3899661873ce (patch) | |
tree | 6fdd5c254f518ac0f55503b429061b1b9aa1ada5 /drivers/gpu/drm/drm_edid.c | |
parent | drm/edid: add single point of return to drm_do_get_edid() (diff) | |
download | linux-f1e4c916f97f6adc0848515d269b3899661873ce.tar.xz linux-f1e4c916f97f6adc0848515d269b3899661873ce.zip |
drm/edid: add EDID block count and size helpers
Add some helpers to figure out the EDID extension block count, block
count, size, pointers to blocks.
Unfortunately, we'll need to cast away the const in a few places where
we actually need to access the data.
v3: fix (!edid_extension_block_count(edid) == 0) (kernel test robot)
v2: fix s/j/i/ introduced in a rebase
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/dc7b0850293d837439fb3914c8a9d81e39018b4b.1649685475.git.jani.nikula@intel.com
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
-rw-r--r-- | drivers/gpu/drm/drm_edid.c | 80 |
1 files changed, 57 insertions, 23 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index d2e1c101575d..324ce8467915 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1568,6 +1568,38 @@ static const struct drm_display_mode edid_4k_modes[] = { /*** DDC fetch and block validation ***/ +static int edid_extension_block_count(const struct edid *edid) +{ + return edid->extensions; +} + +static int edid_block_count(const struct edid *edid) +{ + return edid_extension_block_count(edid) + 1; +} + +static int edid_size_by_blocks(int num_blocks) +{ + return num_blocks * EDID_LENGTH; +} + +static int edid_size(const struct edid *edid) +{ + return edid_size_by_blocks(edid_block_count(edid)); +} + +static const void *edid_block_data(const struct edid *edid, int index) +{ + BUILD_BUG_ON(sizeof(*edid) != EDID_LENGTH); + + return edid + index; +} + +static const void *edid_extension_block_data(const struct edid *edid, int index) +{ + return edid_block_data(edid, index + 1); +} + static const u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; @@ -1654,8 +1686,8 @@ bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2) return false; if (edid1) { - edid1_len = EDID_LENGTH * (1 + edid1->extensions); - edid2_len = EDID_LENGTH * (1 + edid2->extensions); + edid1_len = edid_size(edid1); + edid2_len = edid_size(edid2); if (edid1_len != edid2_len) return false; @@ -1865,14 +1897,16 @@ EXPORT_SYMBOL(drm_edid_block_valid); bool drm_edid_is_valid(struct edid *edid) { int i; - u8 *raw = (u8 *)edid; if (!edid) return false; - for (i = 0; i <= edid->extensions; i++) - if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i, true, NULL)) + for (i = 0; i < edid_block_count(edid); i++) { + void *block = (void *)edid_block_data(edid, i); + + if (!drm_edid_block_valid(block, i, true, NULL)) return false; + } return true; } @@ -1885,13 +1919,13 @@ static struct edid *edid_filter_invalid_blocks(const struct edid *edid, int valid_extensions = edid->extensions - invalid_blocks; int i; - new = kmalloc_array(valid_extensions + 1, EDID_LENGTH, GFP_KERNEL); + new = kmalloc(edid_size_by_blocks(valid_extensions + 1), GFP_KERNEL); if (!new) goto out; dest_block = new; - for (i = 0; i <= edid->extensions; i++) { - const void *block = edid + i; + for (i = 0; i < edid_block_count(edid); i++) { + const void *block = edid_block_data(edid, i); if (edid_block_valid(block, i == 0)) memcpy(dest_block++, block, EDID_LENGTH); @@ -2101,7 +2135,7 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, void *context) { enum edid_block_status status; - int j, invalid_blocks = 0; + int i, invalid_blocks = 0; struct edid *edid, *new; edid = drm_get_override_edid(connector); @@ -2133,20 +2167,20 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, goto fail; } - if (edid->extensions == 0) + if (!edid_extension_block_count(edid)) goto ok; - new = krealloc(edid, (edid->extensions + 1) * EDID_LENGTH, GFP_KERNEL); + new = krealloc(edid, edid_size(edid), GFP_KERNEL); if (!new) goto fail; edid = new; - for (j = 1; j <= edid->extensions; j++) { - void *block = edid + j; + for (i = 1; i < edid_block_count(edid); i++) { + void *block = (void *)edid_block_data(edid, i); - status = edid_block_read(block, j, read_block, context); + status = edid_block_read(block, i, read_block, context); - edid_block_status_print(status, block, j); + edid_block_status_print(status, block, i); if (!edid_block_status_valid(status, edid_block_tag(block))) { if (status == EDID_BLOCK_READ_FAIL) @@ -2156,7 +2190,7 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, } if (invalid_blocks) { - connector_bad_edid(connector, edid, edid->extensions + 1); + connector_bad_edid(connector, edid, edid_block_count(edid)); edid = edid_filter_invalid_blocks(edid, invalid_blocks); } @@ -2321,7 +2355,7 @@ EXPORT_SYMBOL(drm_get_edid_switcheroo); */ struct edid *drm_edid_duplicate(const struct edid *edid) { - return kmemdup(edid, (edid->extensions + 1) * EDID_LENGTH, GFP_KERNEL); + return kmemdup(edid, edid_size(edid), GFP_KERNEL); } EXPORT_SYMBOL(drm_edid_duplicate); @@ -2505,8 +2539,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 = 1; i <= edid->extensions; i++) { - const u8 *ext = (const u8 *)edid + (i * EDID_LENGTH); + for (i = 0; i < edid_extension_block_count(edid); i++) { + const u8 *ext = edid_extension_block_data(edid, i); switch (*ext) { case CEA_EXT: @@ -3476,17 +3510,17 @@ const u8 *drm_find_edid_extension(const struct edid *edid, int i; /* No EDID or EDID extensions */ - if (edid == NULL || edid->extensions == 0) + if (!edid || !edid_extension_block_count(edid)) return NULL; /* Find CEA extension */ - for (i = *ext_index; i < edid->extensions; i++) { - edid_ext = (const u8 *)edid + EDID_LENGTH * (i + 1); + for (i = *ext_index; i < edid_extension_block_count(edid); i++) { + edid_ext = edid_extension_block_data(edid, i); if (edid_block_tag(edid_ext) == ext_id) break; } - if (i >= edid->extensions) + if (i >= edid_extension_block_count(edid)) return NULL; *ext_index = i + 1; |