Skip to content

Commit 794aca0

Browse files
committed
drm/edid: use struct drm_edid for override/firmware EDID
There's a lot going on here, but the main thing is switching the firmware EDID loader to use struct drm_edid. Unfortunately, it's difficult to reasonably split to smaller pieces. Convert the EDID loader to struct drm_edid. There's a functional change in validation; it no longer tries to fix errors or filter invalid blocks. It's stricter in this sense. Hopefully this will not be an issue. As a by-product, this change also allows HF-EEODB extended EDIDs to be passed via override/firmware EDID. Signed-off-by: Jani Nikula <[email protected]> Reviewed-by: Ville Syrjälä <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/e64267c28eca483e83c802bc06ddd149bdcdfc66.1666614699.git.jani.nikula@intel.com
1 parent a05992d commit 794aca0

File tree

3 files changed

+36
-86
lines changed

3 files changed

+36
-86
lines changed

drivers/gpu/drm/drm_edid.c

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2202,25 +2202,20 @@ static void connector_bad_edid(struct drm_connector *connector,
22022202
}
22032203

22042204
/* Get override or firmware EDID */
2205-
static struct edid *drm_get_override_edid(struct drm_connector *connector,
2206-
size_t *alloc_size)
2205+
static const struct drm_edid *drm_edid_override_get(struct drm_connector *connector)
22072206
{
2208-
struct edid *override = NULL;
2207+
const struct drm_edid *override = NULL;
22092208

22102209
mutex_lock(&connector->edid_override_mutex);
22112210

22122211
if (connector->edid_override)
2213-
override = drm_edid_duplicate(connector->edid_override->edid);
2212+
override = drm_edid_dup(connector->edid_override);
22142213

22152214
mutex_unlock(&connector->edid_override_mutex);
22162215

22172216
if (!override)
22182217
override = drm_edid_load_firmware(connector);
22192218

2220-
/* FIXME: Get alloc size from deeper down the stack */
2221-
if (!IS_ERR_OR_NULL(override) && alloc_size)
2222-
*alloc_size = edid_size(override);
2223-
22242219
return IS_ERR(override) ? NULL : override;
22252220
}
22262221

@@ -2296,14 +2291,14 @@ int drm_edid_override_reset(struct drm_connector *connector)
22962291
*/
22972292
int drm_edid_override_connector_update(struct drm_connector *connector)
22982293
{
2299-
struct edid *override;
2294+
const struct drm_edid *override;
23002295
int num_modes = 0;
23012296

2302-
override = drm_get_override_edid(connector, NULL);
2297+
override = drm_edid_override_get(connector);
23032298
if (override) {
2304-
drm_connector_update_edid_property(connector, override);
2305-
num_modes = drm_add_edid_modes(connector, override);
2306-
kfree(override);
2299+
num_modes = drm_edid_connector_update(connector, override);
2300+
2301+
drm_edid_free(override);
23072302

23082303
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] adding %d modes via fallback override/firmware EDID\n",
23092304
connector->base.id, connector->name, num_modes);
@@ -2354,12 +2349,19 @@ static struct edid *_drm_do_get_edid(struct drm_connector *connector,
23542349
{
23552350
enum edid_block_status status;
23562351
int i, num_blocks, invalid_blocks = 0;
2352+
const struct drm_edid *override;
23572353
struct edid *edid, *new;
23582354
size_t alloc_size = EDID_LENGTH;
23592355

2360-
edid = drm_get_override_edid(connector, &alloc_size);
2361-
if (edid)
2356+
override = drm_edid_override_get(connector);
2357+
if (override) {
2358+
alloc_size = override->size;
2359+
edid = kmemdup(override->edid, alloc_size, GFP_KERNEL);
2360+
drm_edid_free(override);
2361+
if (!edid)
2362+
return NULL;
23622363
goto ok;
2364+
}
23632365

23642366
edid = kmalloc(alloc_size, GFP_KERNEL);
23652367
if (!edid)

drivers/gpu/drm/drm_edid_load.c

Lines changed: 17 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -159,22 +159,12 @@ static const u8 generic_edid[GENERIC_EDIDS][128] = {
159159
},
160160
};
161161

162-
static int edid_size(const u8 *edid, int data_size)
163-
{
164-
if (data_size < EDID_LENGTH)
165-
return 0;
166-
167-
return (edid[0x7e] + 1) * EDID_LENGTH;
168-
}
169-
170-
static void *edid_load(struct drm_connector *connector, const char *name)
162+
static const struct drm_edid *edid_load(struct drm_connector *connector, const char *name)
171163
{
172164
const struct firmware *fw = NULL;
173165
const u8 *fwdata;
174-
u8 *edid;
166+
const struct drm_edid *drm_edid;
175167
int fwsize, builtin;
176-
int i, valid_extensions = 0;
177-
bool print_bad_edid = !connector->bad_edid_counter || drm_debug_enabled(DRM_UT_KMS);
178168

179169
builtin = match_string(generic_edid_name, GENERIC_EDIDS, name);
180170
if (builtin >= 0) {
@@ -203,69 +193,26 @@ static void *edid_load(struct drm_connector *connector, const char *name)
203193
fwsize = fw->size;
204194
}
205195

206-
if (edid_size(fwdata, fwsize) != fwsize) {
207-
DRM_ERROR("Size of EDID firmware \"%s\" is invalid "
208-
"(expected %d, got %d\n", name,
209-
edid_size(fwdata, fwsize), (int)fwsize);
210-
edid = ERR_PTR(-EINVAL);
211-
goto out;
212-
}
213-
214-
edid = kmemdup(fwdata, fwsize, GFP_KERNEL);
215-
if (edid == NULL) {
216-
edid = ERR_PTR(-ENOMEM);
217-
goto out;
218-
}
219-
220-
if (!drm_edid_block_valid(edid, 0, print_bad_edid,
221-
&connector->edid_corrupt)) {
222-
connector->bad_edid_counter++;
223-
DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ",
224-
name);
225-
kfree(edid);
226-
edid = ERR_PTR(-EINVAL);
227-
goto out;
228-
}
229-
230-
for (i = 1; i <= edid[0x7e]; i++) {
231-
if (i != valid_extensions + 1)
232-
memcpy(edid + (valid_extensions + 1) * EDID_LENGTH,
233-
edid + i * EDID_LENGTH, EDID_LENGTH);
234-
if (drm_edid_block_valid(edid + i * EDID_LENGTH, i,
235-
print_bad_edid,
236-
NULL))
237-
valid_extensions++;
238-
}
239-
240-
if (valid_extensions != edid[0x7e]) {
241-
u8 *new_edid;
196+
drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Loaded %s firmware EDID \"%s\"\n",
197+
connector->base.id, connector->name,
198+
builtin >= 0 ? "built-in" : "external", name);
242199

243-
edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
244-
DRM_INFO("Found %d valid extensions instead of %d in EDID data "
245-
"\"%s\" for connector \"%s\"\n", valid_extensions,
246-
edid[0x7e], name, connector->name);
247-
edid[0x7e] = valid_extensions;
248-
249-
new_edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH,
250-
GFP_KERNEL);
251-
if (new_edid)
252-
edid = new_edid;
200+
drm_edid = drm_edid_alloc(fwdata, fwsize);
201+
if (!drm_edid_valid(drm_edid)) {
202+
drm_err(connector->dev, "Invalid firmware EDID \"%s\"\n", name);
203+
drm_edid_free(drm_edid);
204+
drm_edid = ERR_PTR(-EINVAL);
253205
}
254206

255-
DRM_INFO("Got %s EDID base block and %d extension%s from "
256-
"\"%s\" for connector \"%s\"\n", (builtin >= 0) ? "built-in" :
257-
"external", valid_extensions, valid_extensions == 1 ? "" : "s",
258-
name, connector->name);
259-
260-
out:
261207
release_firmware(fw);
262-
return edid;
208+
209+
return drm_edid;
263210
}
264211

265-
struct edid *drm_edid_load_firmware(struct drm_connector *connector)
212+
const struct drm_edid *drm_edid_load_firmware(struct drm_connector *connector)
266213
{
267214
char *edidname, *last, *colon, *fwstr, *edidstr, *fallback = NULL;
268-
struct edid *edid;
215+
const struct drm_edid *drm_edid;
269216

270217
if (edid_firmware[0] == '\0')
271218
return ERR_PTR(-ENOENT);
@@ -308,8 +255,9 @@ struct edid *drm_edid_load_firmware(struct drm_connector *connector)
308255
if (*last == '\n')
309256
*last = '\0';
310257

311-
edid = edid_load(connector, edidname);
258+
drm_edid = edid_load(connector, edidname);
259+
312260
kfree(fwstr);
313261

314-
return edid;
262+
return drm_edid;
315263
}

include/drm/drm_edid.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,11 +388,11 @@ int drm_av_sync_delay(struct drm_connector *connector,
388388
const struct drm_display_mode *mode);
389389

390390
#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
391-
struct edid *drm_edid_load_firmware(struct drm_connector *connector);
391+
const struct drm_edid *drm_edid_load_firmware(struct drm_connector *connector);
392392
int __drm_set_edid_firmware_path(const char *path);
393393
int __drm_get_edid_firmware_path(char *buf, size_t bufsize);
394394
#else
395-
static inline struct edid *
395+
static inline const struct drm_edid *
396396
drm_edid_load_firmware(struct drm_connector *connector)
397397
{
398398
return ERR_PTR(-ENOENT);

0 commit comments

Comments
 (0)