ref: 8067368e10330a67550f9e3ee353da858266a6eb
parent: e34fa15921cd76d78e7adc28e471204de036d66a
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Feb 1 21:58:59 EST 2015
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
--- a/sys/src/cmd/aux/vga/db.c
+++ b/sys/src/cmd/aux/vga/db.c
@@ -16,20 +16,35 @@
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 *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);
-
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 @@
return ap->val;
ap = ap->next;
}
-
return 0;
}
--- 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,20 +181,22 @@
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;
@@ -202,8 +203,9 @@
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 @@
}
assert(p == (uchar*)v+8+10+2+5+10+3+16+72);
- return 0;
+ return e;
}
Flag edidflags[] = {
--- a/sys/src/cmd/aux/vga/edid.h
+++ /dev/null
@@ -1,50 +1,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);
--- 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 @@
Reg lvds;
Reg vgacntrl;
-
- Edid *adpaedid;
- Edid *lvdsedid;
};
static u32int
@@ -465,8 +461,13 @@
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 @@
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 @@
snarfedid(Igfx *igfx, int port, int addr)
{
uchar buf[256], tmp[256];
- Edid *e;
int i;
/* read twice */
@@ -1424,13 +1415,7 @@
}
}
- e = malloc(sizeof(Edid));
- if(parseedid128(e, buf) != 0){
- free(e);
- return nil;
- }
-
- return e;
+ return parseedid128(buf);
}
Ctlr igfx = {
--- a/sys/src/cmd/aux/vga/main.c
+++ b/sys/src/cmd/aux/vga/main.c
@@ -17,6 +17,7 @@
{
Ctlr *ctlr;
Attr *attr;
+ int i;
if(vga->mode)
dbdumpmode(vga->mode);
@@ -37,6 +38,12 @@
(*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 @@
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 @@
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){
--- a/sys/src/cmd/aux/vga/mkfile
+++ b/sys/src/cmd/aux/vga/mkfile
@@ -68,7 +68,6 @@
HFILES=\
pci.h\
vga.h\
- edid.h\
UPDATE=\
mkfile\
--- a/sys/src/cmd/aux/vga/vesa.c
+++ b/sys/src/cmd/aux/vga/vesa.c
@@ -6,7 +6,6 @@
#include "pci.h"
#include "vga.h"
-#include "edid.h"
typedef struct Vbe Vbe;
typedef struct Vmode Vmode;
@@ -49,7 +48,6 @@
#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 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 @@
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 @@
}
Mode*
-dbvesamode(char *size)
+dbvesamode(Vga *vga, char *size)
{
int i, width, display;
int oldmode, olddisplay;
@@ -217,8 +196,10 @@
*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 @@
/* 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 @@
}
static void
-dump(Vga*, Ctlr*)
+dump(Vga *, Ctlr*)
{
int i;
char did[0x200];
@@ -341,8 +322,6 @@
for(i=0x100; i<0x1FF; i++)
if(!did[i])
vbeprintmodeinfo(vbe, i, " (unoffered)");
- if(edid != nil)
- printedid(edid);
}
static int
@@ -644,16 +623,11 @@
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 @@
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 @@
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
--- a/sys/src/cmd/aux/vga/vga.h
+++ b/sys/src/cmd/aux/vga/vga.h
@@ -82,12 +82,12 @@
};
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 @@
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 @@
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 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 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 @@
#pragma varargck argpos error 1
#pragma varargck argpos trace 1
+#pragma varargck argpos mkattr 3