aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/via/via_aux_edid.c
diff options
context:
space:
mode:
authorFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2012-01-12 07:52:37 -0500
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2012-02-13 02:28:14 -0500
commit5dc5f61813a9c3ab7dd0a6982ad044834134db5a (patch)
tree4a50b6713eed9d2d01d1e4cdbc8ecd1a4393e035 /drivers/video/via/via_aux_edid.c
parent2c4c8a8a73b64a8ea86ad85d8a59a5914d2f81ea (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.c59
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
28static const char *name = "EDID"; 30static const char *name = "EDID";
29 31
30 32
33static 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
59static 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
76static 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
31void via_aux_edid_probe(struct via_aux_bus *bus) 84void 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);