diff options
author | Dave Airlie <airlied@redhat.com> | 2020-04-22 10:40:34 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2020-04-22 10:41:35 +1000 |
commit | 1aa63ddf726ea049279989b93b69b57ce6efd75b (patch) | |
tree | b2850db923425621e7830918569572de9a22c86b /drivers/gpu/drm/drm_edid.c | |
parent | 774f1eeb18b016eee460e060a786eee83b14d007 (diff) | |
parent | 14d0066b8477775971db7d0ef03c86fefe4d5bf2 (diff) |
Merge tag 'drm-misc-next-2020-04-14' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 5.8:
UAPI Changes:
- drm: error out with EBUSY when device has existing master
- drm: rework SET_MASTER and DROP_MASTER perm handling
Cross-subsystem Changes:
- mm: export two symbols from slub/slob
- fbdev: savage: fix -Wextra build warning
- video: omap2: Use scnprintf() for avoiding potential buffer overflow
Core Changes:
- Remove drm_pci.h
- drm_pci_{alloc/free)() are now legacy
- Introduce managed DRM resourcesA
- Allow drivers to subclass struct drm_framebuffer
- Introduce struct drm_afbc_framebuffer and helpers
- fbdev: remove return value from generic fbdev setup
- Introduce simple-encoder helper
- vram-helpers: set fence on plane
- dp_mst: ACT timeout improvements
- dp_mst: Remove drm_dp_mst_has_audio()
- TTM: ttm_trace_dma_{map/unmap}() cleanups
- dma-buf: add flag for PCIP2P support
- EDID: Various improvements
- Encoder: cleanup semantics of possible_clones and possible_crtcs
- VBLANK documentation updates
- Writeback documentation updates
Driver Changes:
- Convert several drivers to i2c_new_client_device()
- Drop explicit drm_mode_config_cleanup() calls from drivers
- Auto-release device structures with drmm_add_final_kfree()
- Init bfdev console after registering DRM device
- Make various .debugfs functions return 0 unconditionally; ignore errors
- video: Use scnprintf() to avoid buffer overflows
- Convert drivers to simple encoders
- drm/amdgpu: note that we can handle peer2peer DMA-buf
- drm/amdgpu: add support for exporting VRAM using DMA-buf v3
- drm/kirin: Revert change to register connectors
- drm/lima: Add optional devfreq and cooling device support
- drm/lima: Various improvements wrt. task handling
- drm/panel: nt39016: Support multiple modes and 50Hz
- drm/panel: Support Leadtek LTK050H3146W
- drm/rockchip: Add support for afbc
- drm/virtio: Various cleanups
- drm/hisilicon/hibmc: Enforce 128-byte stride alignment
- drm/qxl: Fix notify port address of cursor ring buffer
- drm/sun4i: Improvements to format handling
- drm/bridge: dw-hdmi: Various improvements
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20200414090738.GA16827@linux-uq9g
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
-rw-r--r-- | drivers/gpu/drm/drm_edid.c | 103 |
1 files changed, 46 insertions, 57 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 116451101426..43b6ca364daa 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1583,8 +1583,6 @@ module_param_named(edid_fixup, edid_fixup, int, 0400); MODULE_PARM_DESC(edid_fixup, "Minimum number of valid EDID header bytes (0-8, default 6)"); -static void drm_get_displayid(struct drm_connector *connector, - struct edid *edid); static int validate_displayid(u8 *displayid, int length, int idx); static int drm_edid_block_checksum(const u8 *raw_edid) @@ -2018,18 +2016,13 @@ EXPORT_SYMBOL(drm_probe_ddc); struct edid *drm_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) { - struct edid *edid; - if (connector->force == DRM_FORCE_OFF) return NULL; if (connector->force == DRM_FORCE_UNSPECIFIED && !drm_probe_ddc(adapter)) return NULL; - edid = drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter); - if (edid) - drm_get_displayid(connector, edid); - return edid; + return drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter); } EXPORT_SYMBOL(drm_get_edid); @@ -3212,16 +3205,33 @@ static u8 *drm_find_edid_extension(const struct edid *edid, int ext_id) } -static u8 *drm_find_displayid_extension(const struct edid *edid) +static u8 *drm_find_displayid_extension(const struct edid *edid, + int *length, int *idx) { - return drm_find_edid_extension(edid, DISPLAYID_EXT); + u8 *displayid = drm_find_edid_extension(edid, DISPLAYID_EXT); + struct displayid_hdr *base; + int ret; + + if (!displayid) + return NULL; + + /* EDID extensions block checksum isn't for us */ + *length = EDID_LENGTH - 1; + *idx = 1; + + ret = validate_displayid(displayid, *length, *idx); + if (ret) + return NULL; + + base = (struct displayid_hdr *)&displayid[*idx]; + *length = *idx + sizeof(*base) + base->bytes; + + return displayid; } static u8 *drm_find_cea_extension(const struct edid *edid) { - int ret; - int idx = 1; - int length = EDID_LENGTH; + int length, idx; struct displayid_block *block; u8 *cea; u8 *displayid; @@ -3232,14 +3242,10 @@ static u8 *drm_find_cea_extension(const struct edid *edid) return cea; /* CEA blocks can also be found embedded in a DisplayID block */ - displayid = drm_find_displayid_extension(edid); + displayid = drm_find_displayid_extension(edid, &length, &idx); if (!displayid) return NULL; - ret = validate_displayid(displayid, length, idx); - if (ret) - return NULL; - idx += sizeof(struct displayid_hdr); for_each_displayid_db(displayid, block, idx, length) { if (block->tag == DATA_BLOCK_CTA) { @@ -5084,7 +5090,7 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi static int validate_displayid(u8 *displayid, int length, int idx) { - int i; + int i, dispid_length; u8 csum = 0; struct displayid_hdr *base; @@ -5093,15 +5099,18 @@ static int validate_displayid(u8 *displayid, int length, int idx) DRM_DEBUG_KMS("base revision 0x%x, length %d, %d %d\n", base->rev, base->bytes, base->prod_id, base->ext_count); - if (base->bytes + 5 > length - idx) + /* +1 for DispID checksum */ + dispid_length = sizeof(*base) + base->bytes + 1; + if (dispid_length > length - idx) return -EINVAL; - for (i = idx; i <= base->bytes + 5; i++) { - csum += displayid[i]; - } + + for (i = 0; i < dispid_length; i++) + csum += displayid[idx + i]; if (csum) { DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum); return -EINVAL; } + return 0; } @@ -5180,20 +5189,14 @@ static int add_displayid_detailed_modes(struct drm_connector *connector, struct edid *edid) { u8 *displayid; - int ret; - int idx = 1; - int length = EDID_LENGTH; + int length, idx; struct displayid_block *block; int num_modes = 0; - displayid = drm_find_displayid_extension(edid); + displayid = drm_find_displayid_extension(edid, &length, &idx); if (!displayid) return 0; - ret = validate_displayid(displayid, length, idx); - if (ret) - return 0; - idx += sizeof(struct displayid_hdr); for_each_displayid_db(displayid, block, idx, length) { switch (block->tag) { @@ -5782,9 +5785,9 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, EXPORT_SYMBOL(drm_hdmi_vendor_infoframe_from_display_mode); static int drm_parse_tiled_block(struct drm_connector *connector, - struct displayid_block *block) + const struct displayid_block *block) { - struct displayid_tiled_block *tile = (struct displayid_tiled_block *)block; + const struct displayid_tiled_block *tile = (struct displayid_tiled_block *)block; u16 w, h; u8 tile_v_loc, tile_h_loc; u8 num_v_tile, num_h_tile; @@ -5835,22 +5838,12 @@ static int drm_parse_tiled_block(struct drm_connector *connector, return 0; } -static int drm_parse_display_id(struct drm_connector *connector, - u8 *displayid, int length, - bool is_edid_extension) +static int drm_displayid_parse_tiled(struct drm_connector *connector, + const u8 *displayid, int length, int idx) { - /* if this is an EDID extension the first byte will be 0x70 */ - int idx = 0; - struct displayid_block *block; + const struct displayid_block *block; int ret; - if (is_edid_extension) - idx = 1; - - ret = validate_displayid(displayid, length, idx); - if (ret) - return ret; - idx += sizeof(struct displayid_hdr); for_each_displayid_db(displayid, block, idx, length) { DRM_DEBUG_KMS("block id 0x%x, rev %d, len %d\n", @@ -5862,12 +5855,6 @@ static int drm_parse_display_id(struct drm_connector *connector, if (ret) return ret; break; - case DATA_BLOCK_TYPE_1_DETAILED_TIMING: - /* handled in mode gathering code. */ - break; - case DATA_BLOCK_CTA: - /* handled in the cea parser code. */ - break; default: DRM_DEBUG_KMS("found DisplayID tag 0x%x, unhandled\n", block->tag); break; @@ -5876,19 +5863,21 @@ static int drm_parse_display_id(struct drm_connector *connector, return 0; } -static void drm_get_displayid(struct drm_connector *connector, - struct edid *edid) +void drm_update_tile_info(struct drm_connector *connector, + const struct edid *edid) { - void *displayid = NULL; + const void *displayid = NULL; + int length, idx; int ret; + connector->has_tile = false; - displayid = drm_find_displayid_extension(edid); + displayid = drm_find_displayid_extension(edid, &length, &idx); if (!displayid) { /* drop reference to any tile group we had */ goto out_drop_ref; } - ret = drm_parse_display_id(connector, displayid, EDID_LENGTH, true); + ret = drm_displayid_parse_tiled(connector, displayid, length, idx); if (ret < 0) goto out_drop_ref; if (!connector->has_tile) |