diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-02-02 02:58:59 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-02-02 02:58:59 +0100 |
commit | 8067368e10330a67550f9e3ee353da858266a6eb (patch) | |
tree | da29460c6810b48ee67b2d330c04a22a3ab35379 | |
parent | e34fa15921cd76d78e7adc28e471204de036d66a (diff) | |
download | plan9front-8067368e10330a67550f9e3ee353da858266a6eb.tar.xz |
aux/vga: use optional edid information to determine mode when vgadb fails
igfx and vesa can determine monitor timing information from ddc
and store the edid info for connected monitors in vga->edid[].
when monitor type cannot be found in vgadb, we consult the edid
information and make a mode based on the edid info.
this avoids having to maintain a vgadb entry for each monitor.
monitor can be set to "[width]x[height]@[freq]Hz" for a specific
edid setting. when not found, a mode is searched based on the
size.
so the following should work:
aux/vga -m 1366x768@60Hz -l 1366x768x32
aux/vga -m auto -l 1366x768x32
-rw-r--r-- | sys/src/cmd/aux/vga/db.c | 32 | ||||
-rw-r--r-- | sys/src/cmd/aux/vga/edid.c | 16 | ||||
-rw-r--r-- | sys/src/cmd/aux/vga/edid.h | 50 | ||||
-rw-r--r-- | sys/src/cmd/aux/vga/igfx.c | 31 | ||||
-rw-r--r-- | sys/src/cmd/aux/vga/main.c | 64 | ||||
-rw-r--r-- | sys/src/cmd/aux/vga/mkfile | 1 | ||||
-rw-r--r-- | sys/src/cmd/aux/vga/vesa.c | 68 | ||||
-rw-r--r-- | sys/src/cmd/aux/vga/vga.h | 59 |
8 files changed, 174 insertions, 147 deletions
diff --git a/sys/src/cmd/aux/vga/db.c b/sys/src/cmd/aux/vga/db.c index e8227443e..2602001bf 100644 --- a/sys/src/cmd/aux/vga/db.c +++ b/sys/src/cmd/aux/vga/db.c @@ -16,20 +16,35 @@ dbopen(char* dbname) return db; } +Attr* +mkattr(Attr *tail, char *attr, char *fmt, ...) +{ + char val[1024]; + va_list list; + Attr *a; + + va_start(list, fmt); + snprint(val, sizeof(val), fmt, list); + va_end(list); + + a = alloc(sizeof(Attr)); + a->attr = alloc(strlen(attr)+1); + strcpy(a->attr, attr); + a->val = alloc(strlen(val)+1); + strcpy(a->val, val); + a->next = tail; + + return a; +} + static void addattr(Attr** app, Ndbtuple* t) { - Attr *attr, *l; - - attr = alloc(sizeof(Attr)); - attr->attr = alloc(strlen(t->attr)+1); - strcpy(attr->attr, t->attr); - attr->val = alloc(strlen(t->val)+1); - strcpy(attr->val, t->val); + Attr *l; for(l = *app; l; l = l->next) app = &l->next; - *app = attr; + *app = mkattr(nil, t->attr, "%s", t->val); } char* @@ -40,7 +55,6 @@ dbattr(Attr* ap, char* attr) return ap->val; ap = ap->next; } - return 0; } diff --git a/sys/src/cmd/aux/vga/edid.c b/sys/src/cmd/aux/vga/edid.c index ba95d2611..e0ac6ce58 100644 --- a/sys/src/cmd/aux/vga/edid.c +++ b/sys/src/cmd/aux/vga/edid.c @@ -5,7 +5,6 @@ #include "pci.h" #include "vga.h" -#include "edid.h" static Modelist* addmode(Modelist *l, Mode m) @@ -182,28 +181,31 @@ decodesti(Mode *m, uchar *p) return vesalookup(m, str); } -int -parseedid128(Edid *e, void *v) +Edid* +parseedid128(void *v) { static uchar magic[8] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 }; uchar *p, *q, sum; int dpms, estab, i, m, vid; Mode mode; + Edid *e; - memset(e, 0, sizeof *e); + e = alloc(sizeof(Edid)); p = (uchar*)v; if(memcmp(p, magic, 8) != 0) { + free(e); werrstr("bad edid header"); - return -1; + return nil; } sum = 0; for(i=0; i<128; i++) sum += p[i]; if(sum != 0) { + free(e); werrstr("bad edid checksum"); - return -1; + return nil; } p += 8; @@ -342,7 +344,7 @@ parseedid128(Edid *e, void *v) } assert(p == (uchar*)v+8+10+2+5+10+3+16+72); - return 0; + return e; } Flag edidflags[] = { diff --git a/sys/src/cmd/aux/vga/edid.h b/sys/src/cmd/aux/vga/edid.h deleted file mode 100644 index 84321dbba..000000000 --- a/sys/src/cmd/aux/vga/edid.h +++ /dev/null @@ -1,50 +0,0 @@ -typedef struct Modelist Modelist; -typedef struct Edid Edid; -typedef struct Flag Flag; - -struct Edid { - char mfr[4]; /* manufacturer */ - char serialstr[16]; /* serial number as string (in extended data) */ - char name[16]; /* monitor name as string (in extended data) */ - ushort product; /* product code, 0 = unused */ - ulong serial; /* serial number, 0 = unused */ - uchar version; /* major version number */ - uchar revision; /* minor version number */ - uchar mfrweek; /* week of manufacture, 0 = unused */ - int mfryear; /* year of manufacture, 0 = unused */ - uchar dxcm; /* horizontal image size in cm. */ - uchar dycm; /* vertical image size in cm. */ - int gamma; /* gamma*100 */ - int rrmin; /* minimum vertical refresh rate */ - int rrmax; /* maximum vertical refresh rate */ - int hrmin; /* minimum horizontal refresh rate */ - int hrmax; /* maximum horizontal refresh rate */ - ulong pclkmax; /* maximum pixel clock */ - int flags; - Modelist *modelist; /* list of supported modes */ -}; - -struct Modelist -{ - Mode; - Modelist *next; -}; - -struct Flag { - int bit; - char *desc; -}; - -enum { - Fdigital = 1<<0, /* is a digital display */ - Fdpmsstandby = 1<<1, /* supports DPMS standby mode */ - Fdpmssuspend = 1<<2, /* supports DPMS suspend mode */ - Fdpmsactiveoff = 1<<3, /* supports DPMS active off mode */ - Fmonochrome = 1<<4, /* is a monochrome display */ - Fgtf = 1<<5, /* supports VESA GTF: see /public/doc/vesa/gtf10.pdf */ -}; -Flag edidflags[]; -void printflags(Flag *f, int b); - -int parseedid128(Edid *e, void *v); -void printedid(Edid *e); diff --git a/sys/src/cmd/aux/vga/igfx.c b/sys/src/cmd/aux/vga/igfx.c index 9367d1788..4b8a3900e 100644 --- a/sys/src/cmd/aux/vga/igfx.c +++ b/sys/src/cmd/aux/vga/igfx.c @@ -4,7 +4,6 @@ #include "pci.h" #include "vga.h" -#include "edid.h" typedef struct Reg Reg; typedef struct Dpll Dpll; @@ -156,9 +155,6 @@ struct Igfx { Reg lvds; Reg vgacntrl; - - Edid *adpaedid; - Edid *lvdsedid; }; static u32int @@ -465,8 +461,13 @@ snarf(Vga* vga, Ctlr* ctlr) for(x=0; x<igfx->npipe; x++) snarfpipe(igfx, x); - igfx->adpaedid = snarfedid(igfx, 2, 0x50); - igfx->lvdsedid = snarfedid(igfx, 3, 0x50); + vga->edid[0] = snarfedid(igfx, 2, 0x50); + vga->edid[1] = snarfedid(igfx, 3, 0x50); + if(vga->edid[1] != nil){ + Modelist *l; + for(l = vga->edid[1]->modelist; l != nil; l = l->next) + l->attr = mkattr(l->attr, "lcd", "1"); + } ctlr->flag |= Fsnarf; } @@ -1332,15 +1333,6 @@ dump(Vga* vga, Ctlr* ctlr) dumpreg(ctlr->name, "sdvoc", igfx->sdvoc); dumpreg(ctlr->name, "vgacntrl", igfx->vgacntrl); - - if(igfx->adpaedid != nil){ - Bprint(&stdout, "edid adpa\n"); - printedid(igfx->adpaedid); - } - if(igfx->lvdsedid != nil){ - Bprint(&stdout, "edid lvds\n"); - printedid(igfx->lvdsedid); - } } enum { @@ -1404,7 +1396,6 @@ static Edid* snarfedid(Igfx *igfx, int port, int addr) { uchar buf[256], tmp[256]; - Edid *e; int i; /* read twice */ @@ -1424,13 +1415,7 @@ snarfedid(Igfx *igfx, int port, int addr) } } - e = malloc(sizeof(Edid)); - if(parseedid128(e, buf) != 0){ - free(e); - return nil; - } - - return e; + return parseedid128(buf); } Ctlr igfx = { diff --git a/sys/src/cmd/aux/vga/main.c b/sys/src/cmd/aux/vga/main.c index a42e8e648..188801e89 100644 --- a/sys/src/cmd/aux/vga/main.c +++ b/sys/src/cmd/aux/vga/main.c @@ -17,6 +17,7 @@ dump(Vga* vga) { Ctlr *ctlr; Attr *attr; + int i; if(vga->mode) dbdumpmode(vga->mode); @@ -37,6 +38,12 @@ dump(Vga* vga) (*ctlr->dump)(vga, ctlr); ctlr->flag |= Fdump; } + + for(i=0; i < nelem(vga->edid); i++){ + if(vga->edid[i]) + printedid(vga->edid[i]); + } + Bprint(&stdout, "\n"); } @@ -135,6 +142,54 @@ linear(Vga* vga) vgactlw("linear", "0"); } +static Mode* +dbedidmode(Vga *vga, char *type, char *size) +{ + char buf[32], *p; + int i, x, y, z; + Modelist *l; + Mode *m; + + z = 32; + x = y = 0; + snprint(buf, sizeof(buf), "%s", size); + if((p = strchr(buf, 'x')) != nil){ + *p++ = 0; + x = atoi(buf); + y = atoi(p); + if((p = strchr(p, 'x')) != nil){ + *p++ = 0; + z = atoi(p); + } + } + + for(i=0; i<nelem(vga->edid); i++){ + if(vga->edid[i] == nil) + continue; + for(l = vga->edid[i]->modelist; l != nil; l = l->next) + if(strcmp(l->name, type) == 0) + goto found; + } + for(i=0; i<nelem(vga->edid); i++){ + if(vga->edid[i] == nil) + continue; + for(l = vga->edid[i]->modelist; l != nil; l = l->next) + if((x == 0 || l->x == x) && (y == 0 || l->y == y)) + goto found; + } + return nil; + +found: + m = alloc(sizeof(Mode)); + *m = *((Mode*)l); + m->z = z; + x = m->x; + y = m->y; + snprint(m->type, sizeof(m->type), "%s", type); + snprint(m->size, sizeof(m->size), "%dx%dx%d", x, y, z); + return m; +} + char* chanstr[32+1] = { [1] "k1", @@ -291,10 +346,13 @@ main(int argc, char** argv) if(vga->vesa){ strcpy(monitordb, "vesa bios"); - vga->mode = dbvesamode(psize); - }else + vga->mode = dbvesamode(vga, psize); + }else { vga->mode = dbmode(monitordb, type, psize); - if(vga->mode == 0) + if(vga->mode == nil) + vga->mode = dbedidmode(vga, type, psize); + } + if(vga->mode == nil) error("main: %s@%s not in %s\n", type, psize, monitordb); if(virtual){ diff --git a/sys/src/cmd/aux/vga/mkfile b/sys/src/cmd/aux/vga/mkfile index 6d821110d..4fbb2cca0 100644 --- a/sys/src/cmd/aux/vga/mkfile +++ b/sys/src/cmd/aux/vga/mkfile @@ -68,7 +68,6 @@ OFILES=\ HFILES=\ pci.h\ vga.h\ - edid.h\ UPDATE=\ mkfile\ diff --git a/sys/src/cmd/aux/vga/vesa.c b/sys/src/cmd/aux/vga/vesa.c index e10b7c2b8..a2fa7699d 100644 --- a/sys/src/cmd/aux/vga/vesa.c +++ b/sys/src/cmd/aux/vga/vesa.c @@ -6,7 +6,6 @@ typedef struct Ureg Ureg; #include "pci.h" #include "vga.h" -#include "edid.h" typedef struct Vbe Vbe; typedef struct Vmode Vmode; @@ -49,7 +48,6 @@ struct Vmode #define PLONG(p, v) (p)[0] = (v); (p)[1] = (v)>>8; (p)[2] = (v)>>16; (p)[3] = (v)>>24 static Vbe *vbe; -static Edid *edid; static int dspcon; /* connected displays bitmask */ static int dspact; /* active displays bitmask */ @@ -65,7 +63,7 @@ void vbeprintinfo(Vbe*); void vbeprintmodeinfo(Vbe*, int, char*); int vbesnarf(Vbe*, Vga*); void vesaddc(void); -int vbeddcedid(Vbe *vbe, Edid *e); +Edid* vbeddcedid(Vbe *vbe); uchar* vbesetup(Vbe*, Ureg*, int); int vbecall(Vbe*, Ureg*); int setdisplay(Vbe *vbe, int display); @@ -99,25 +97,6 @@ dbvesa(Vga* vga) return 1; } -static Attr* -newattr(Attr *tail, char *attr, char *fmt, ...) -{ - va_list list; - char *val; - Attr *a; - - va_start(list, fmt); - val = vsmprint(fmt, list); - va_end(list); - - a = alloc(sizeof(Attr)); - a->attr = attr; - a->val = val; - a->next = tail; - - return a; -} - static char* cracksize(char *size, char **scale, int *display) { @@ -141,7 +120,7 @@ cracksize(char *size, char **scale, int *display) } Mode* -dbvesamode(char *size) +dbvesamode(Vga *vga, char *size) { int i, width, display; int oldmode, olddisplay; @@ -217,8 +196,10 @@ havemode: *m = *vesamodes[i]; break; } - if(edid != nil){ - for(l = edid->modelist; l; l = l->next){ + for(i=0; i<nelem(vga->edid); i++){ + if(vga->edid[i] == nil) + continue; + for(l = vga->edid[i]->modelist; l; l = l->next){ if(l->x != vm.dx || l->y != vm.dy) continue; *m = *((Mode*)l); @@ -234,14 +215,14 @@ havemode: /* account for framebuffer stride */ width = vm.bpl * 8 / m->z; if(width > m->x) - m->attr = newattr(m->attr, "virtx", "%d", width); + m->attr = mkattr(m->attr, "virtx", "%d", width); if(scale != nil) - m->attr = newattr(m->attr, "scale", "%s", scale); + m->attr = mkattr(m->attr, "scale", "%s", scale); if(display != 0) - m->attr = newattr(m->attr, "display", "%d", display); + m->attr = mkattr(m->attr, "display", "%d", display); - m->attr = newattr(m->attr, "id", "0x%x", vm.id); + m->attr = mkattr(m->attr, "id", "0x%x", vm.id); return m; } @@ -317,7 +298,7 @@ load(Vga* vga, Ctlr* ctlr) } static void -dump(Vga*, Ctlr*) +dump(Vga *, Ctlr*) { int i; char did[0x200]; @@ -341,8 +322,6 @@ dump(Vga*, Ctlr*) for(i=0x100; i<0x1FF; i++) if(!did[i]) vbeprintmodeinfo(vbe, i, " (unoffered)"); - if(edid != nil) - printedid(edid); } static int @@ -644,16 +623,11 @@ vbesnarf(Vbe *vbe, Vga *vga) dspact = u.cx; } - else if(memcmp(oem, "NVIDIA", 6) == 0 && 0) /* untested */ + else if(memcmp(oem, "NVIDIA", 6) == 0) setscale = nvidiascale; - if(edid == nil){ - edid = alloc(sizeof(Edid)); - if(vbeddcedid(vbe, edid) < 0){ - free(edid); - edid = nil; - } - } + vga->edid[0] = vbeddcedid(vbe); + return 0; } @@ -864,10 +838,8 @@ vesatextmode(void) error("vbesetmode: %r\n"); } -int parseedid128(Edid *e, void *v); - -int -vbeddcedid(Vbe *vbe, Edid *e) +Edid* +vbeddcedid(Vbe *vbe) { uchar *p; Ureg u; @@ -875,12 +847,8 @@ vbeddcedid(Vbe *vbe, Edid *e) p = vbesetup(vbe, &u, 0x4F15); u.bx = 0x0001; if(vbecall(vbe, &u) < 0) - return -1; - if(parseedid128(e, p) < 0){ - werrstr("parseedid128: %r"); - return -1; - } - return 0; + return nil; + return parseedid128(p); } int diff --git a/sys/src/cmd/aux/vga/vga.h b/sys/src/cmd/aux/vga/vga.h index f4606b943..cf6f735f0 100644 --- a/sys/src/cmd/aux/vga/vga.h +++ b/sys/src/cmd/aux/vga/vga.h @@ -82,12 +82,12 @@ enum { /* flag */ }; typedef struct Attr Attr; -typedef struct Attr { +struct Attr { char* attr; char* val; Attr* next; -} Attr; +}; typedef struct Mode { char type[Namelen+1]; /* monitor type e.g. "vs1782" */ @@ -124,6 +124,39 @@ typedef struct Mode { Attr* attr; } Mode; +typedef struct Modelist Modelist; +struct Modelist { + Mode; + Modelist *next; +}; + +typedef struct Edid { + char mfr[4]; /* manufacturer */ + char serialstr[16]; /* serial number as string (in extended data) */ + char name[16]; /* monitor name as string (in extended data) */ + ushort product; /* product code, 0 = unused */ + ulong serial; /* serial number, 0 = unused */ + uchar version; /* major version number */ + uchar revision; /* minor version number */ + uchar mfrweek; /* week of manufacture, 0 = unused */ + int mfryear; /* year of manufacture, 0 = unused */ + uchar dxcm; /* horizontal image size in cm. */ + uchar dycm; /* vertical image size in cm. */ + int gamma; /* gamma*100 */ + int rrmin; /* minimum vertical refresh rate */ + int rrmax; /* maximum vertical refresh rate */ + int hrmin; /* minimum horizontal refresh rate */ + int hrmax; /* maximum horizontal refresh rate */ + ulong pclkmax; /* maximum pixel clock */ + int flags; + Modelist *modelist; /* list of supported modes */ +} Edid; + +typedef struct Flag { + int bit; + char *desc; +} Flag; + /* * The sizes of the register sets are large as many SVGA and GUI chips have extras. * The Crt registers are ushorts in order to keep overflow bits handy. @@ -188,11 +221,13 @@ typedef struct Vga { Ctlr* ramdac; Ctlr* clock; Ctlr* hwgc; - Ctlr* vesa; + Ctlr* vesa; Ctlr* link; int linear; Attr* attr; + Edid* edid[8]; /* edid information for connected monitors */ + void* private; } Vga; @@ -247,11 +282,26 @@ extern Ctlr *ctlrs[]; extern ushort dacxreg[4]; /* db.c */ +extern Attr* mkattr(Attr*, char*, char*, ...); extern char* dbattr(Attr*, char*); extern int dbctlr(char*, Vga*); extern Mode* dbmode(char*, char*, char*); extern void dbdumpmode(Mode*); +/* edid.c */ +enum { + Fdigital = 1<<0, /* is a digital display */ + Fdpmsstandby = 1<<1, /* supports DPMS standby mode */ + Fdpmssuspend = 1<<2, /* supports DPMS suspend mode */ + Fdpmsactiveoff = 1<<3, /* supports DPMS active off mode */ + Fmonochrome = 1<<4, /* is a monochrome display */ + Fgtf = 1<<5, /* supports VESA GTF: see /public/doc/vesa/gtf10.pdf */ +}; +extern Flag edidflags[]; +extern void printflags(Flag *f, int b); +extern Edid* parseedid128(void *v); +extern void printedid(Edid *e); + /* error.c */ extern void error(char*, ...); extern void trace(char*, ...); @@ -435,7 +485,7 @@ extern Ctlr generic; extern Ctlr vesa; extern Ctlr softhwgc; /* has to go somewhere */ extern int dbvesa(Vga*); -extern Mode *dbvesamode(char*); +extern Mode *dbvesamode(Vga*,char*); extern void vesatextmode(void); /* vesadb.c */ @@ -466,3 +516,4 @@ extern Ctlr mga4xxhwgc; #pragma varargck argpos error 1 #pragma varargck argpos trace 1 +#pragma varargck argpos mkattr 3 |