Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.15 176 lines 3.9 kB view raw
1// SPDX-License-Identifier: MIT 2/* 3 * Copyright © 2021 Intel Corporation 4 */ 5 6#include <drm/drm_edid.h> 7#include <drm/drm_print.h> 8 9#include "drm_crtc_internal.h" 10#include "drm_displayid_internal.h" 11 12static const struct displayid_header * 13displayid_get_header(const u8 *displayid, int length, int index) 14{ 15 const struct displayid_header *base; 16 17 if (sizeof(*base) > length - index) 18 return ERR_PTR(-EINVAL); 19 20 base = (const struct displayid_header *)&displayid[index]; 21 22 return base; 23} 24 25static const struct displayid_header * 26validate_displayid(const u8 *displayid, int length, int idx) 27{ 28 int i, dispid_length; 29 u8 csum = 0; 30 const struct displayid_header *base; 31 32 base = displayid_get_header(displayid, length, idx); 33 if (IS_ERR(base)) 34 return base; 35 36 /* +1 for DispID checksum */ 37 dispid_length = sizeof(*base) + base->bytes + 1; 38 if (dispid_length > length - idx) 39 return ERR_PTR(-EINVAL); 40 41 for (i = 0; i < dispid_length; i++) 42 csum += displayid[idx + i]; 43 if (csum) { 44 DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum); 45 return ERR_PTR(-EINVAL); 46 } 47 48 return base; 49} 50 51static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid, 52 int *length, int *idx, 53 int *ext_index) 54{ 55 const struct displayid_header *base; 56 const u8 *displayid; 57 58 displayid = drm_edid_find_extension(drm_edid, DISPLAYID_EXT, ext_index); 59 if (!displayid) 60 return NULL; 61 62 /* EDID extensions block checksum isn't for us */ 63 *length = EDID_LENGTH - 1; 64 *idx = 1; 65 66 base = validate_displayid(displayid, *length, *idx); 67 if (IS_ERR(base)) 68 return NULL; 69 70 *length = *idx + sizeof(*base) + base->bytes; 71 72 return displayid; 73} 74 75void displayid_iter_edid_begin(const struct drm_edid *drm_edid, 76 struct displayid_iter *iter) 77{ 78 memset(iter, 0, sizeof(*iter)); 79 80 iter->drm_edid = drm_edid; 81} 82 83static const struct displayid_block * 84displayid_iter_block(const struct displayid_iter *iter) 85{ 86 const struct displayid_block *block; 87 88 if (!iter->section) 89 return NULL; 90 91 block = (const struct displayid_block *)&iter->section[iter->idx]; 92 93 if (iter->idx + sizeof(*block) <= iter->length && 94 iter->idx + sizeof(*block) + block->num_bytes <= iter->length) 95 return block; 96 97 return NULL; 98} 99 100const struct displayid_block * 101__displayid_iter_next(struct displayid_iter *iter) 102{ 103 const struct displayid_block *block; 104 105 if (!iter->drm_edid) 106 return NULL; 107 108 if (iter->section) { 109 /* current block should always be valid */ 110 block = displayid_iter_block(iter); 111 if (WARN_ON(!block)) { 112 iter->section = NULL; 113 iter->drm_edid = NULL; 114 return NULL; 115 } 116 117 /* next block in section */ 118 iter->idx += sizeof(*block) + block->num_bytes; 119 120 block = displayid_iter_block(iter); 121 if (block) 122 return block; 123 } 124 125 for (;;) { 126 /* The first section we encounter is the base section */ 127 bool base_section = !iter->section; 128 129 iter->section = drm_find_displayid_extension(iter->drm_edid, 130 &iter->length, 131 &iter->idx, 132 &iter->ext_index); 133 if (!iter->section) { 134 iter->drm_edid = NULL; 135 return NULL; 136 } 137 138 /* Save the structure version and primary use case. */ 139 if (base_section) { 140 const struct displayid_header *base; 141 142 base = displayid_get_header(iter->section, iter->length, 143 iter->idx); 144 if (!IS_ERR(base)) { 145 iter->version = base->rev; 146 iter->primary_use = base->prod_id; 147 } 148 } 149 150 iter->idx += sizeof(struct displayid_header); 151 152 block = displayid_iter_block(iter); 153 if (block) 154 return block; 155 } 156} 157 158void displayid_iter_end(struct displayid_iter *iter) 159{ 160 memset(iter, 0, sizeof(*iter)); 161} 162 163/* DisplayID Structure Version/Revision from the Base Section. */ 164u8 displayid_version(const struct displayid_iter *iter) 165{ 166 return iter->version; 167} 168 169/* 170 * DisplayID Primary Use Case (2.0+) or Product Type Identifier (1.0-1.3) from 171 * the Base Section. 172 */ 173u8 displayid_primary_use(const struct displayid_iter *iter) 174{ 175 return iter->primary_use; 176}