1 // SPDX-License-Identifier: MIT
3 * Copyright © 2021 Intel Corporation
6 #include <drm/drm_edid.h>
7 #include <drm/drm_print.h>
9 #include "drm_crtc_internal.h"
10 #include "drm_displayid_internal.h"
12 static const struct displayid_header
*
13 displayid_get_header(const u8
*displayid
, int length
, int index
)
15 const struct displayid_header
*base
;
17 if (sizeof(*base
) > length
- index
)
18 return ERR_PTR(-EINVAL
);
20 base
= (const struct displayid_header
*)&displayid
[index
];
25 static const struct displayid_header
*
26 validate_displayid(const u8
*displayid
, int length
, int idx
)
30 const struct displayid_header
*base
;
32 base
= displayid_get_header(displayid
, length
, idx
);
36 /* +1 for DispID checksum */
37 dispid_length
= sizeof(*base
) + base
->bytes
+ 1;
38 if (dispid_length
> length
- idx
)
39 return ERR_PTR(-EINVAL
);
41 for (i
= 0; i
< dispid_length
; i
++)
42 csum
+= displayid
[idx
+ i
];
44 DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum
);
45 return ERR_PTR(-EINVAL
);
51 static const u8
*drm_find_displayid_extension(const struct drm_edid
*drm_edid
,
52 int *length
, int *idx
,
55 const struct displayid_header
*base
;
58 displayid
= drm_edid_find_extension(drm_edid
, DISPLAYID_EXT
, ext_index
);
62 /* EDID extensions block checksum isn't for us */
63 *length
= EDID_LENGTH
- 1;
66 base
= validate_displayid(displayid
, *length
, *idx
);
70 *length
= *idx
+ sizeof(*base
) + base
->bytes
;
75 void displayid_iter_edid_begin(const struct drm_edid
*drm_edid
,
76 struct displayid_iter
*iter
)
78 memset(iter
, 0, sizeof(*iter
));
80 iter
->drm_edid
= drm_edid
;
83 static const struct displayid_block
*
84 displayid_iter_block(const struct displayid_iter
*iter
)
86 const struct displayid_block
*block
;
91 block
= (const struct displayid_block
*)&iter
->section
[iter
->idx
];
93 if (iter
->idx
+ sizeof(*block
) <= iter
->length
&&
94 iter
->idx
+ sizeof(*block
) + block
->num_bytes
<= iter
->length
)
100 const struct displayid_block
*
101 __displayid_iter_next(struct displayid_iter
*iter
)
103 const struct displayid_block
*block
;
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
;
117 /* next block in section */
118 iter
->idx
+= sizeof(*block
) + block
->num_bytes
;
120 block
= displayid_iter_block(iter
);
126 /* The first section we encounter is the base section */
127 bool base_section
= !iter
->section
;
129 iter
->section
= drm_find_displayid_extension(iter
->drm_edid
,
133 if (!iter
->section
) {
134 iter
->drm_edid
= NULL
;
138 /* Save the structure version and primary use case. */
140 const struct displayid_header
*base
;
142 base
= displayid_get_header(iter
->section
, iter
->length
,
145 iter
->version
= base
->rev
;
146 iter
->primary_use
= base
->prod_id
;
150 iter
->idx
+= sizeof(struct displayid_header
);
152 block
= displayid_iter_block(iter
);
158 void displayid_iter_end(struct displayid_iter
*iter
)
160 memset(iter
, 0, sizeof(*iter
));
163 /* DisplayID Structure Version/Revision from the Base Section. */
164 u8
displayid_version(const struct displayid_iter
*iter
)
166 return iter
->version
;
170 * DisplayID Primary Use Case (2.0+) or Product Type Identifier (1.0-1.3) from
173 u8
displayid_primary_use(const struct displayid_iter
*iter
)
175 return iter
->primary_use
;