diff options
author | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2012-01-12 07:52:37 -0500 |
---|---|---|
committer | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2012-02-13 02:28:14 -0500 |
commit | 5dc5f61813a9c3ab7dd0a6982ad044834134db5a (patch) | |
tree | 4a50b6713eed9d2d01d1e4cdbc8ecd1a4393e035 /drivers/video/via/via_aux_edid.c | |
parent | 2c4c8a8a73b64a8ea86ad85d8a59a5914d2f81ea (diff) |
viafb: add initial EDID support
This patch adds support for using EDID data on CRT and DVP1 for
initial configuration if viafb_mode or viafb_mode1 are not present.
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Diffstat (limited to 'drivers/video/via/via_aux_edid.c')
-rw-r--r-- | drivers/video/via/via_aux_edid.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/drivers/video/via/via_aux_edid.c b/drivers/video/via/via_aux_edid.c index 547bff53a448..03f7a41c8a3f 100644 --- a/drivers/video/via/via_aux_edid.c +++ b/drivers/video/via/via_aux_edid.c | |||
@@ -22,18 +22,75 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/fb.h> | ||
25 | #include "via_aux.h" | 26 | #include "via_aux.h" |
27 | #include "../edid.h" | ||
26 | 28 | ||
27 | 29 | ||
28 | static const char *name = "EDID"; | 30 | static const char *name = "EDID"; |
29 | 31 | ||
30 | 32 | ||
33 | static void query_edid(struct via_aux_drv *drv) | ||
34 | { | ||
35 | struct fb_monspecs *spec = drv->data; | ||
36 | unsigned char edid[EDID_LENGTH]; | ||
37 | bool valid = false; | ||
38 | |||
39 | if (spec) | ||
40 | fb_destroy_modedb(spec->modedb); | ||
41 | else | ||
42 | spec = kmalloc(sizeof(*spec), GFP_KERNEL); | ||
43 | |||
44 | spec->version = spec->revision = 0; | ||
45 | if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) { | ||
46 | fb_edid_to_monspecs(edid, spec); | ||
47 | valid = spec->version || spec->revision; | ||
48 | } | ||
49 | |||
50 | if (!valid) { | ||
51 | kfree(spec); | ||
52 | spec = NULL; | ||
53 | } else | ||
54 | printk(KERN_DEBUG "EDID: %s %s\n", spec->manufacturer, spec->monitor); | ||
55 | |||
56 | drv->data = spec; | ||
57 | } | ||
58 | |||
59 | static const struct fb_videomode *get_preferred_mode(struct via_aux_drv *drv) | ||
60 | { | ||
61 | struct fb_monspecs *spec = drv->data; | ||
62 | int i; | ||
63 | |||
64 | if (!spec || !spec->modedb || !(spec->misc & FB_MISC_1ST_DETAIL)) | ||
65 | return NULL; | ||
66 | |||
67 | for (i = 0; i < spec->modedb_len; i++) { | ||
68 | if (spec->modedb[i].flag & FB_MODE_IS_FIRST && | ||
69 | spec->modedb[i].flag & FB_MODE_IS_DETAILED) | ||
70 | return &spec->modedb[i]; | ||
71 | } | ||
72 | |||
73 | return NULL; | ||
74 | } | ||
75 | |||
76 | static void cleanup(struct via_aux_drv *drv) | ||
77 | { | ||
78 | struct fb_monspecs *spec = drv->data; | ||
79 | |||
80 | if (spec) | ||
81 | fb_destroy_modedb(spec->modedb); | ||
82 | } | ||
83 | |||
31 | void via_aux_edid_probe(struct via_aux_bus *bus) | 84 | void via_aux_edid_probe(struct via_aux_bus *bus) |
32 | { | 85 | { |
33 | struct via_aux_drv drv = { | 86 | struct via_aux_drv drv = { |
34 | .bus = bus, | 87 | .bus = bus, |
35 | .addr = 0x50, | 88 | .addr = 0x50, |
36 | .name = name}; | 89 | .name = name, |
90 | .cleanup = cleanup, | ||
91 | .get_preferred_mode = get_preferred_mode}; | ||
92 | |||
93 | query_edid(&drv); | ||
37 | 94 | ||
38 | /* as EDID devices can be connected/disconnected just add the driver */ | 95 | /* as EDID devices can be connected/disconnected just add the driver */ |
39 | via_aux_add(&drv); | 96 | via_aux_add(&drv); |