diff options
| -rw-r--r-- | drivers/video/fbmon.c | 58 |
1 files changed, 30 insertions, 28 deletions
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index a0b5a93b72d2..b25399abcf49 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c | |||
| @@ -973,58 +973,56 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs) | |||
| 973 | DPRINTK("========================================\n"); | 973 | DPRINTK("========================================\n"); |
| 974 | } | 974 | } |
| 975 | 975 | ||
| 976 | /** | ||
| 977 | * fb_edid_add_monspecs() - add monitor video modes from E-EDID data | ||
| 978 | * @edid: 128 byte array with an E-EDID block | ||
| 979 | * @spacs: monitor specs to be extended | ||
| 980 | */ | ||
| 976 | void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs) | 981 | void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs) |
| 977 | { | 982 | { |
| 978 | unsigned char *block; | 983 | unsigned char *block; |
| 979 | struct fb_videomode *mode, *m; | 984 | struct fb_videomode *m; |
| 980 | int num = 0, i, first = 1; | 985 | int num = 0, i; |
| 986 | u8 edt[(128 - 4) / DETAILED_TIMING_DESCRIPTION_SIZE]; | ||
| 981 | 987 | ||
| 982 | if (edid == NULL) | 988 | if (!edid) |
| 983 | return; | 989 | return; |
| 984 | 990 | ||
| 985 | if (!edid_checksum(edid)) | 991 | if (!edid_checksum(edid)) |
| 986 | return; | 992 | return; |
| 987 | 993 | ||
| 988 | if (edid[0] != 0x2) | 994 | if (edid[0] != 0x2 || |
| 995 | edid[2] < 4 || edid[2] > 128 - DETAILED_TIMING_DESCRIPTION_SIZE) | ||
| 989 | return; | 996 | return; |
| 990 | 997 | ||
| 991 | mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL); | 998 | block = edid + edid[2]; |
| 992 | if (mode == NULL) | ||
| 993 | return; | ||
| 994 | |||
| 995 | block = edid + edid[0x2]; | ||
| 996 | 999 | ||
| 997 | DPRINTK(" Extended Detailed Timings\n"); | 1000 | DPRINTK(" Extended Detailed Timings\n"); |
| 998 | 1001 | ||
| 999 | for (i = 0; i < (128 - edid[0x2]) / DETAILED_TIMING_DESCRIPTION_SIZE; | 1002 | for (i = 0; i < (128 - edid[2]) / DETAILED_TIMING_DESCRIPTION_SIZE; |
| 1000 | i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) { | 1003 | i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) |
| 1001 | if (!(block[0] == 0x00 && block[1] == 0x00)) { | 1004 | if (PIXEL_CLOCK) |
| 1002 | get_detailed_timing(block, &mode[num]); | 1005 | edt[num++] = block - edid; |
| 1003 | if (first) { | ||
| 1004 | mode[num].flag |= FB_MODE_IS_FIRST; | ||
| 1005 | first = 0; | ||
| 1006 | } | ||
| 1007 | num++; | ||
| 1008 | } | ||
| 1009 | } | ||
| 1010 | 1006 | ||
| 1011 | /* Yikes, EDID data is totally useless */ | 1007 | /* Yikes, EDID data is totally useless */ |
| 1012 | if (!num) { | 1008 | if (!num) |
| 1013 | kfree(mode); | ||
| 1014 | return; | 1009 | return; |
| 1015 | } | ||
| 1016 | 1010 | ||
| 1017 | m = kzalloc((specs->modedb_len + num) * | 1011 | m = kzalloc((specs->modedb_len + num) * |
| 1018 | sizeof(struct fb_videomode), GFP_KERNEL); | 1012 | sizeof(struct fb_videomode), GFP_KERNEL); |
| 1019 | 1013 | ||
| 1020 | if (!m) { | 1014 | if (!m) |
| 1021 | kfree(mode); | ||
| 1022 | return; | 1015 | return; |
| 1016 | |||
| 1017 | memcpy(m, specs->modedb, specs->modedb_len * sizeof(struct fb_videomode)); | ||
| 1018 | |||
| 1019 | for (i = specs->modedb_len; i < specs->modedb_len + num; i++) { | ||
| 1020 | get_detailed_timing(edid + edt[i - specs->modedb_len], &m[i]); | ||
| 1021 | if (i == specs->modedb_len) | ||
| 1022 | m[i].flag |= FB_MODE_IS_FIRST; | ||
| 1023 | pr_debug("Adding %ux%u@%u\n", m[i].xres, m[i].yres, m[i].refresh); | ||
| 1023 | } | 1024 | } |
| 1024 | 1025 | ||
| 1025 | memmove(m, specs->modedb, specs->modedb_len * sizeof(struct fb_videomode)); | ||
| 1026 | memmove(m + specs->modedb_len, mode, num * sizeof(struct fb_videomode)); | ||
| 1027 | kfree(mode); | ||
| 1028 | kfree(specs->modedb); | 1026 | kfree(specs->modedb); |
| 1029 | specs->modedb = m; | 1027 | specs->modedb = m; |
| 1030 | specs->modedb_len = specs->modedb_len + num; | 1028 | specs->modedb_len = specs->modedb_len + num; |
| @@ -1346,6 +1344,9 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs) | |||
| 1346 | { | 1344 | { |
| 1347 | specs = NULL; | 1345 | specs = NULL; |
| 1348 | } | 1346 | } |
| 1347 | void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs) | ||
| 1348 | { | ||
| 1349 | } | ||
| 1349 | void fb_destroy_modedb(struct fb_videomode *modedb) | 1350 | void fb_destroy_modedb(struct fb_videomode *modedb) |
| 1350 | { | 1351 | { |
| 1351 | } | 1352 | } |
| @@ -1453,6 +1454,7 @@ EXPORT_SYMBOL(fb_firmware_edid); | |||
| 1453 | 1454 | ||
| 1454 | EXPORT_SYMBOL(fb_parse_edid); | 1455 | EXPORT_SYMBOL(fb_parse_edid); |
| 1455 | EXPORT_SYMBOL(fb_edid_to_monspecs); | 1456 | EXPORT_SYMBOL(fb_edid_to_monspecs); |
| 1457 | EXPORT_SYMBOL(fb_edid_add_monspecs); | ||
| 1456 | EXPORT_SYMBOL(fb_get_mode); | 1458 | EXPORT_SYMBOL(fb_get_mode); |
| 1457 | EXPORT_SYMBOL(fb_validate_mode); | 1459 | EXPORT_SYMBOL(fb_validate_mode); |
| 1458 | EXPORT_SYMBOL(fb_destroy_modedb); | 1460 | EXPORT_SYMBOL(fb_destroy_modedb); |
