From: Egbert Eich <eich@suse.de>
To: dri-devel@lists.freedesktop.org
Cc: Egbert Eich <eich@suse.de>, Takashi Iwai <tiwai@suse.com>
Subject: [PATCH 08/17] DRM/KMS/EDID: Use Extension Block Fixup Code also for 'firmware' EDID.
Date: Mon, 19 Nov 2012 15:23:09 -0500 [thread overview]
Message-ID: <1353356598-10634-9-git-send-email-eich@suse.de> (raw)
In-Reply-To: <1353356598-10634-1-git-send-email-eich@suse.de>
Signed-off-by: Egbert Eich <eich@suse.de>
---
drivers/gpu/drm/drm_edid.c | 77 ++++++++++++++++++++++++++++++++-------
drivers/gpu/drm/drm_edid_load.c | 54 ++++++---------------------
include/drm/drm_edid.h | 1 +
3 files changed, 77 insertions(+), 55 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index d1b9d67..7bdae6e 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -408,6 +408,29 @@ fixup_blockmaps(u8 **blockp, int eblock_cnt)
return eblock_cnt;
}
+static int
+fixup_edid(u8 **blockp, int valid_extensions)
+{
+ u8 *new = NULL;
+
+ if (valid_extensions != (*blockp)[EDID_EXTENSION_FLAG_OFFSET]) {
+
+ if (valid_extensions)
+ valid_extensions = fixup_blockmaps(blockp, valid_extensions);
+
+ if (valid_extensions >= 0) {
+ (*blockp)[EDID_CHECKSUM_OFFSET] += (*blockp)[EDID_EXTENSION_FLAG_OFFSET] - valid_extensions;
+ (*blockp)[EDID_EXTENSION_FLAG_OFFSET] = valid_extensions;
+ new = krealloc(*blockp, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
+ }
+ if (!new)
+ kfree(*blockp);
+
+ *blockp = new;
+ }
+ return (new ? valid_extensions : -ENOMEM);
+}
+
static u8 *
drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
{
@@ -474,19 +497,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
}
no_more:
- if (valid_extensions != block[EDID_EXTENSION_FLAG_OFFSET]) {
- if (valid_extensions)
- valid_extensions = fixup_blockmaps(&block, valid_extensions);
- if (valid_extensions >= 0) {
- block[EDID_CHECKSUM_OFFSET] += block[EDID_EXTENSION_FLAG_OFFSET] - valid_extensions;
- block[EDID_EXTENSION_FLAG_OFFSET] = valid_extensions;
- new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
- if (!new)
- goto out;
- } else
- goto out;
- block = new;
- }
+ fixup_edid(&block, valid_extensions);
return block;
@@ -503,6 +514,46 @@ out:
}
/**
+ * Validate an entire EDID blob.
+ * \param connector: drm_connector struct of the used connector.
+ * \param blockp: pointer to address of an raw EDID data block.
+ * \param len: size if block in bytes.
+ *
+ * validate block and return corrected block in \param block.
+ * \return: number of valid extensions or -errno if unsuccessful.
+ */
+int
+drm_validate_edid_blob(struct drm_connector *connector, u8 **blockp, int len)
+{
+ int n_blocks = len / EDID_LENGTH;
+ int valid_extensions = 0, ret = 0;
+ bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);
+
+ if (!blockp || !*blockp)
+ ret = -EINVAL;
+ else if (!n_blocks || !drm_edid_block_valid(*blockp, 0, print_bad_edid)) {
+ kfree(*blockp);
+ *blockp = NULL;
+ ret = -EINVAL;
+ }
+ if (!ret) {
+ n_blocks--;
+ if ((*blockp)[EDID_EXTENSION_FLAG_OFFSET] < n_blocks)
+ n_blocks = (*blockp)[EDID_EXTENSION_FLAG_OFFSET];
+
+ while (n_blocks--) {
+ if (drm_edid_block_valid(*blockp + (valid_extensions + 1) * EDID_LENGTH,
+ valid_extensions + 1, print_bad_edid))
+ valid_extensions++;
+ }
+ ret = fixup_edid(blockp, valid_extensions);
+ }
+ if (ret < 0)
+ connector->bad_edid_counter++;
+ return ret;
+}
+
+/**
* Probe DDC presence.
*
* \param adapter : i2c device adaptor
diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c
index 38d3943..6541c1f 100644
--- a/drivers/gpu/drm/drm_edid_load.c
+++ b/drivers/gpu/drm/drm_edid_load.c
@@ -119,11 +119,10 @@ static u8 *edid_load(struct drm_connector *connector, char *name,
{
const struct firmware *fw;
struct platform_device *pdev;
- u8 *fwdata = NULL, *edid, *new_edid;
+ u8 *fwdata = NULL;
+ struct edid *edid;
int fwsize, expected;
int builtin = 0, err = 0;
- int i, valid_extensions = 0;
- bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);
pdev = platform_device_register_simple(connector_name, -1, NULL, 0);
if (IS_ERR(pdev)) {
@@ -137,7 +136,7 @@ static u8 *edid_load(struct drm_connector *connector, char *name,
platform_device_unregister(pdev);
if (err) {
- i = 0;
+ int i = 0;
while (i < GENERIC_EDIDS && strcmp(name, generic_edid_name[i]))
i++;
if (i < GENERIC_EDIDS) {
@@ -174,49 +173,20 @@ static u8 *edid_load(struct drm_connector *connector, char *name,
}
memcpy(edid, fwdata, fwsize);
- if (!drm_edid_block_valid(edid, 0, print_bad_edid)) {
- connector->bad_edid_counter++;
- DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ",
- name);
- kfree(edid);
- err = -EINVAL;
- goto relfw_out;
- }
-
- for (i = 1; i <= edid[0x7e]; i++) {
- if (i != valid_extensions + 1)
- memcpy(edid + (valid_extensions + 1) * EDID_LENGTH,
- edid + i * EDID_LENGTH, EDID_LENGTH);
- if (drm_edid_block_valid(edid + i * EDID_LENGTH, i, print_bad_edid))
- valid_extensions++;
- }
-
- if (valid_extensions != edid[0x7e]) {
- edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
- DRM_INFO("Found %d valid extensions instead of %d in EDID data "
- "\"%s\" for connector \"%s\"\n", valid_extensions,
- edid[0x7e], name, connector_name);
- edid[0x7e] = valid_extensions;
- new_edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH,
- GFP_KERNEL);
- if (new_edid == NULL) {
- err = -ENOMEM;
- kfree(edid);
- goto relfw_out;
- }
- edid = new_edid;
- }
-
- DRM_INFO("Got %s EDID base block and %d extension%s from "
- "\"%s\" for connector \"%s\"\n", builtin ? "built-in" :
- "external", valid_extensions, valid_extensions == 1 ? "" : "s",
- name, connector_name);
+ err = drm_validate_edid_blob(connector, (u8 **)&edid, fwsize);
+ if (err < 0)
+ DRM_ERROR("EDID firmware \"%s\" is invalid ", name);
+ else
+ DRM_INFO("Got %s EDID base block and %d extension%s from "
+ "\"%s\" for connector \"%s\"\n", builtin ? "built-in" :
+ "external", edid->extensions, edid->extensions == 1 ? "" : "s",
+ name, connector_name);
relfw_out:
release_firmware(fw);
out:
- if (err)
+ if (err < 0)
return ERR_PTR(err);
return edid;
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 0cac551..3e8ef06 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -253,5 +253,6 @@ int drm_av_sync_delay(struct drm_connector *connector,
struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
struct drm_display_mode *mode);
int drm_load_edid_firmware(struct drm_connector *connector);
+int drm_validate_edid_blob(struct drm_connector *connector, u8 **blockp, int len);
#endif /* __DRM_EDID_H__ */
--
1.7.7
next prev parent reply other threads:[~2012-11-19 20:41 UTC|newest]
Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-11-19 20:23 [PATCH 00/17] DRM/KMS/EDID: Various EDID handling related fixes Egbert Eich
2012-11-19 20:23 ` [PATCH 01/17] DRM/KMS/EDID: Mask out Segment Bits when calculating Offset Egbert Eich
2012-11-19 20:23 ` [PATCH 03/17] DRM/KMS/EDID: Return Base EDID block if reading EEDID Blocks fails Egbert Eich
2012-11-19 20:23 ` [PATCH 04/17] DRM/KMS/EDID: Test EDDC if EDID announces more than one Extension Block Egbert Eich
2012-11-19 20:23 ` [PATCH 05/17] DRM/KMS/EDID: Fix up EEDID Map Blocks if Extension block count has changed Egbert Eich
2012-11-20 8:13 ` Takashi Iwai
2012-11-19 20:23 ` [PATCH 06/17] DRM/exynos: Fix Memory Leak: free EDID blcok returned by drm_get_edid() Egbert Eich
2012-11-20 4:17 ` Inki Dae
2012-11-20 9:30 ` [PATCH] drm/exynos: fix memory leak: free EDID block Egbert Eich
2012-11-20 19:58 ` Sean Paul
2012-11-20 20:29 ` Egbert Eich
2012-11-20 21:18 ` Sean Paul
2012-12-14 10:24 ` Jani Nikula
2012-11-21 3:50 ` Inki Dae
2012-11-19 20:23 ` [PATCH 07/17] DRM/KMS/EDID: Move drm_edid_load.o to drm.ko Egbert Eich
2012-11-20 8:26 ` Takashi Iwai
2012-11-19 20:23 ` Egbert Eich [this message]
2012-11-20 8:21 ` [PATCH 08/17] DRM/KMS/EDID: Use Extension Block Fixup Code also for 'firmware' EDID Takashi Iwai
2012-11-19 20:23 ` [PATCH 09/17] DRM/KMS/EDID: Feed 'firmware' supplied EDID blocks whenever the EDID is read Egbert Eich
2012-11-19 20:23 ` [PATCH 10/17] DRM/KMS/EDID: Cache EDID blobs with extensions Egbert Eich
2012-11-20 8:29 ` Takashi Iwai
2012-11-19 20:23 ` [PATCH 11/17] DRM/KMS/EDID: Avoid failing on krealloc on EDID blocks Egbert Eich
2012-11-19 20:23 ` [PATCH 12/17] DRM/KMS/EDID: Consolidate EDID Error Handling Egbert Eich
2012-11-19 20:23 ` [PATCH 13/17] DRM/KMS/EDID: Allow for multiple Connectors when specifying 'firmware'-EDID Files Egbert Eich
2012-11-20 8:38 ` Takashi Iwai
2012-11-19 20:23 ` [PATCH 14/17] DRM/KMS/ast: Include drm_edid.h in file using drm_get_edid() Egbert Eich
2012-11-19 20:23 ` [PATCH 15/17] DRM/KMS/gma500: " Egbert Eich
2012-11-19 20:23 ` [PATCH 16/17] DRM/KMS/mgag200: " Egbert Eich
2012-11-19 20:23 ` [PATCH 17/17] DRM/KMS/EDID: Move EDID related Functions to drm_edid.h Egbert Eich
2012-11-22 10:22 ` [PATCH v2 00/18] DRM/KMS/EDID: Various EDID handling related fixes Egbert Eich
2012-11-22 10:22 ` [PATCH v2 01/18] DRM/KMS/EDID: Mask out Segment Bits when calculating Offset Egbert Eich
2012-11-22 10:22 ` [PATCH v2 02/18] DRM/KMS/EDID: 0x7e -> EDID_EXTENSION_FLAG_OFFSET (v2) Egbert Eich
2012-11-22 10:22 ` [PATCH v2 03/18] DRM/KMS/EDID: Return Base EDID block if reading EEDID Blocks fails (v2) Egbert Eich
2012-11-22 10:22 ` [PATCH v2 04/18] DRM/KMS/EDID: Don't fail when failing to allocate memory for EDID extensions Egbert Eich
2012-11-22 10:22 ` [PATCH v2 05/18] DRM/KMS/EDID: Test EDDC if EDID announces more than one Extension Block (v2) Egbert Eich
2012-11-22 11:20 ` Ville Syrjälä
2012-11-22 12:07 ` Egbert Eich
2012-11-22 12:29 ` Ville Syrjälä
2012-11-22 13:18 ` Egbert Eich
2012-11-22 14:39 ` [PATCH v3] DRM/KMS/EDID: Test EDDC if EDID announces more than one Extension Block (v3) Egbert Eich
2012-11-22 10:22 ` [PATCH v2 06/18] DRM/KMS/EDID: Don't expect extension blocks for EDID Versions < 1.3 Egbert Eich
2012-11-22 10:22 ` [PATCH v2 07/18] DRM/KMS/EDID: Don't reallocate EDID blob when size has shrunk Egbert Eich
2012-11-22 10:22 ` [PATCH v2 08/18] DRM/KMS/EDID: Fix up EEDID Map Blogs if Extension Block Count has changed (v2) Egbert Eich
2012-11-22 10:22 ` [PATCH v2 09/18] DRM/KMS/EDID: Move drm_edid_load.o to drm.ko (v2) Egbert Eich
2012-11-22 10:23 ` [PATCH v2 10/18] DRM/KMS/EDID: Feed 'firmware' supplied EDID blocks whenever the EDID is read (v2) Egbert Eich
2012-11-22 10:23 ` [PATCH v2 11/18] DRM/KMS/EDID: Allow for multiple Connectors when specifying 'firmware'-EDID Files (v2) Egbert Eich
2012-11-22 10:23 ` [PATCH v2 12/18] DRM/KMS/EDID: Use Extension Block Fixup Code also for 'firmware' EDID (v2) Egbert Eich
2012-11-22 10:23 ` [PATCH v2 13/18] DRM/KMS/EDID: Cache EDID blobs with extensions (v2) Egbert Eich
2012-11-22 14:14 ` Ville Syrjälä
2012-11-22 14:29 ` Egbert Eich
2012-11-22 14:43 ` [PATCH v3] DRM/KMS/EDID: Cache EDID blobs with extensions (v3) Egbert Eich
2012-11-22 10:23 ` [PATCH v2 14/18] DRM/KMS/EDID: Consolidate EDID Error Handling (v2) Egbert Eich
2012-11-22 14:44 ` [PATCH v3] DRM/KMS/EDID: Consolidate EDID Error Handling (v3) Egbert Eich
2012-11-22 16:09 ` Ville Syrjälä
2012-11-22 18:28 ` Egbert Eich
2012-11-22 18:54 ` Ville Syrjälä
2012-11-22 20:01 ` Egbert Eich
2012-11-22 18:57 ` [PATCH v4] DRM/KMS/EDID: Consolidate EDID Error Handling (v4) Egbert Eich
2012-11-22 20:29 ` [PATCH v5] DRM/KMS/EDID: Consolidate EDID Error Handling (v5) Egbert Eich
2012-11-22 10:23 ` [PATCH v2 15/18] DRM/KMS/ast: Include drm_edid.h in file using drm_get_edid() Egbert Eich
2012-11-22 10:23 ` [PATCH v2 16/18] DRM/KMS/gma500: " Egbert Eich
2012-11-22 10:23 ` [PATCH v2 17/18] DRM/KMS/mgag200: " Egbert Eich
2012-11-22 10:23 ` [PATCH v2 18/18] DRM/KMS/EDID: Move EDID related Functions to drm_edid.h Egbert Eich
2012-11-22 19:00 ` [PATCH v4] DRM/KMS/EDID: Move EDID related Functions to drm_edid.h (v2) Egbert Eich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1353356598-10634-9-git-send-email-eich@suse.de \
--to=eich@suse.de \
--cc=dri-devel@lists.freedesktop.org \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.