diff options
| author | Jerome Glisse <jglisse@redhat.com> | 2012-08-09 11:25:51 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2012-09-16 21:16:40 -0400 |
| commit | 0b2443ed4e07d7973e4554a2cc166bc35447b59e (patch) | |
| tree | a996dbd03a8480f6473a7ea2fdea3936760de853 | |
| parent | 09e7dcf081b1100d1cdff57fa9eb25c3a834c9d6 (diff) | |
drm/edid: limit printk when facing bad edid
Limit printing bad edid information at one time per connector.
Connector that are connected to a bad monitor/kvm will likely
stay connected to the same bad monitor/kvm and it makes no
sense to keep printing the bad edid message.
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
| -rw-r--r-- | drivers/gpu/drm/drm_edid.c | 22 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_edid_load.c | 6 | ||||
| -rw-r--r-- | include/drm/drm_crtc.h | 3 |
3 files changed, 20 insertions, 11 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index acb489ff3630..de2a0ed8e945 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
| @@ -158,7 +158,7 @@ MODULE_PARM_DESC(edid_fixup, | |||
| 158 | * Sanity check the EDID block (base or extension). Return 0 if the block | 158 | * Sanity check the EDID block (base or extension). Return 0 if the block |
| 159 | * doesn't check out, or 1 if it's valid. | 159 | * doesn't check out, or 1 if it's valid. |
| 160 | */ | 160 | */ |
| 161 | bool drm_edid_block_valid(u8 *raw_edid, int block) | 161 | bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid) |
| 162 | { | 162 | { |
| 163 | int i; | 163 | int i; |
| 164 | u8 csum = 0; | 164 | u8 csum = 0; |
| @@ -181,7 +181,9 @@ bool drm_edid_block_valid(u8 *raw_edid, int block) | |||
| 181 | for (i = 0; i < EDID_LENGTH; i++) | 181 | for (i = 0; i < EDID_LENGTH; i++) |
| 182 | csum += raw_edid[i]; | 182 | csum += raw_edid[i]; |
| 183 | if (csum) { | 183 | if (csum) { |
| 184 | DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); | 184 | if (print_bad_edid) { |
| 185 | DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); | ||
| 186 | } | ||
| 185 | 187 | ||
| 186 | /* allow CEA to slide through, switches mangle this */ | 188 | /* allow CEA to slide through, switches mangle this */ |
| 187 | if (raw_edid[0] != 0x02) | 189 | if (raw_edid[0] != 0x02) |
| @@ -207,7 +209,7 @@ bool drm_edid_block_valid(u8 *raw_edid, int block) | |||
| 207 | return 1; | 209 | return 1; |
| 208 | 210 | ||
| 209 | bad: | 211 | bad: |
| 210 | if (raw_edid) { | 212 | if (raw_edid && print_bad_edid) { |
| 211 | printk(KERN_ERR "Raw EDID:\n"); | 213 | printk(KERN_ERR "Raw EDID:\n"); |
| 212 | print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1, | 214 | print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1, |
| 213 | raw_edid, EDID_LENGTH, false); | 215 | raw_edid, EDID_LENGTH, false); |
| @@ -231,7 +233,7 @@ bool drm_edid_is_valid(struct edid *edid) | |||
| 231 | return false; | 233 | return false; |
| 232 | 234 | ||
| 233 | for (i = 0; i <= edid->extensions; i++) | 235 | for (i = 0; i <= edid->extensions; i++) |
| 234 | if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i)) | 236 | if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i, true)) |
| 235 | return false; | 237 | return false; |
| 236 | 238 | ||
| 237 | return true; | 239 | return true; |
| @@ -316,6 +318,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) | |||
| 316 | { | 318 | { |
| 317 | int i, j = 0, valid_extensions = 0; | 319 | int i, j = 0, valid_extensions = 0; |
| 318 | u8 *block, *new; | 320 | u8 *block, *new; |
| 321 | bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS); | ||
| 319 | 322 | ||
| 320 | if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) | 323 | if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) |
| 321 | return NULL; | 324 | return NULL; |
| @@ -324,7 +327,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) | |||
| 324 | for (i = 0; i < 4; i++) { | 327 | for (i = 0; i < 4; i++) { |
| 325 | if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH)) | 328 | if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH)) |
| 326 | goto out; | 329 | goto out; |
| 327 | if (drm_edid_block_valid(block, 0)) | 330 | if (drm_edid_block_valid(block, 0, print_bad_edid)) |
| 328 | break; | 331 | break; |
| 329 | if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { | 332 | if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { |
| 330 | connector->null_edid_counter++; | 333 | connector->null_edid_counter++; |
| @@ -349,7 +352,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) | |||
| 349 | block + (valid_extensions + 1) * EDID_LENGTH, | 352 | block + (valid_extensions + 1) * EDID_LENGTH, |
| 350 | j, EDID_LENGTH)) | 353 | j, EDID_LENGTH)) |
| 351 | goto out; | 354 | goto out; |
| 352 | if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j)) { | 355 | if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j, print_bad_edid)) { |
| 353 | valid_extensions++; | 356 | valid_extensions++; |
| 354 | break; | 357 | break; |
| 355 | } | 358 | } |
| @@ -372,8 +375,11 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) | |||
| 372 | return block; | 375 | return block; |
| 373 | 376 | ||
| 374 | carp: | 377 | carp: |
| 375 | dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n", | 378 | if (print_bad_edid) { |
| 376 | drm_get_connector_name(connector), j); | 379 | dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n", |
| 380 | drm_get_connector_name(connector), j); | ||
| 381 | } | ||
| 382 | connector->bad_edid_counter++; | ||
| 377 | 383 | ||
| 378 | out: | 384 | out: |
| 379 | kfree(block); | 385 | kfree(block); |
diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c index 186832e1874e..ea9cdab3d431 100644 --- a/drivers/gpu/drm/drm_edid_load.c +++ b/drivers/gpu/drm/drm_edid_load.c | |||
| @@ -123,6 +123,7 @@ static u8 *edid_load(struct drm_connector *connector, char *name, | |||
| 123 | int fwsize, expected; | 123 | int fwsize, expected; |
| 124 | int builtin = 0, err = 0; | 124 | int builtin = 0, err = 0; |
| 125 | int i, valid_extensions = 0; | 125 | int i, valid_extensions = 0; |
| 126 | bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS); | ||
| 126 | 127 | ||
| 127 | pdev = platform_device_register_simple(connector_name, -1, NULL, 0); | 128 | pdev = platform_device_register_simple(connector_name, -1, NULL, 0); |
| 128 | if (IS_ERR(pdev)) { | 129 | if (IS_ERR(pdev)) { |
| @@ -173,7 +174,8 @@ static u8 *edid_load(struct drm_connector *connector, char *name, | |||
| 173 | } | 174 | } |
| 174 | memcpy(edid, fwdata, fwsize); | 175 | memcpy(edid, fwdata, fwsize); |
| 175 | 176 | ||
| 176 | if (!drm_edid_block_valid(edid, 0)) { | 177 | if (!drm_edid_block_valid(edid, 0, print_bad_edid)) { |
| 178 | connector->bad_edid_counter++; | ||
| 177 | DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ", | 179 | DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ", |
| 178 | name); | 180 | name); |
| 179 | kfree(edid); | 181 | kfree(edid); |
| @@ -185,7 +187,7 @@ static u8 *edid_load(struct drm_connector *connector, char *name, | |||
| 185 | if (i != valid_extensions + 1) | 187 | if (i != valid_extensions + 1) |
| 186 | memcpy(edid + (valid_extensions + 1) * EDID_LENGTH, | 188 | memcpy(edid + (valid_extensions + 1) * EDID_LENGTH, |
| 187 | edid + i * EDID_LENGTH, EDID_LENGTH); | 189 | edid + i * EDID_LENGTH, EDID_LENGTH); |
| 188 | if (drm_edid_block_valid(edid + i * EDID_LENGTH, i)) | 190 | if (drm_edid_block_valid(edid + i * EDID_LENGTH, i, print_bad_edid)) |
| 189 | valid_extensions++; | 191 | valid_extensions++; |
| 190 | } | 192 | } |
| 191 | 193 | ||
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 617d87ae2b1a..316ce64e5590 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
| @@ -590,6 +590,7 @@ struct drm_connector { | |||
| 590 | int video_latency[2]; /* [0]: progressive, [1]: interlaced */ | 590 | int video_latency[2]; /* [0]: progressive, [1]: interlaced */ |
| 591 | int audio_latency[2]; | 591 | int audio_latency[2]; |
| 592 | int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */ | 592 | int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */ |
| 593 | unsigned bad_edid_counter; | ||
| 593 | }; | 594 | }; |
| 594 | 595 | ||
| 595 | /** | 596 | /** |
| @@ -1032,7 +1033,7 @@ extern int drm_add_modes_noedid(struct drm_connector *connector, | |||
| 1032 | int hdisplay, int vdisplay); | 1033 | int hdisplay, int vdisplay); |
| 1033 | 1034 | ||
| 1034 | extern int drm_edid_header_is_valid(const u8 *raw_edid); | 1035 | extern int drm_edid_header_is_valid(const u8 *raw_edid); |
| 1035 | extern bool drm_edid_block_valid(u8 *raw_edid, int block); | 1036 | extern bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid); |
| 1036 | extern bool drm_edid_is_valid(struct edid *edid); | 1037 | extern bool drm_edid_is_valid(struct edid *edid); |
| 1037 | struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, | 1038 | struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, |
| 1038 | int hsize, int vsize, int fresh, | 1039 | int hsize, int vsize, int fresh, |
