brintos

brintos / linux-shallow public Read only

0
0
Text · 3.8 KiB · b4fd437 Raw
177 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2021 Intel Corporation4 */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) from171 * the Base Section.172 */173u8 displayid_primary_use(const struct displayid_iter *iter)174{175	return iter->primary_use;176}177