9front - general discussion about 9front
 help / color / mirror / Atom feed
* [9front] [PATCH] aux/vga: return modes according to EDID timing priority order
@ 2022-02-28 21:20 Michael Forney
  2022-02-28 22:06 ` Steve Simon
  0 siblings, 1 reply; 2+ messages in thread
From: Michael Forney @ 2022-02-28 21:20 UTC (permalink / raw)
  To: 9front


EDID 1.3 section 5 gives a table describing the priority order of
timing information. Use this ordering when constructing the EDID
mode list.

Since aux/vga selects the first mode in the modelist that matches
the given size, it will now select the mode of that size with the
highest preference. Or, if you set vgasize=auto (or some other
string without an 'x'), aux/vga will select the Preferred Detailed
Timing.

This should make it unnecessary to modify vgadb in many cases.
---
 sys/src/cmd/aux/vga/edid.c | 133 ++++++++++++++++++++-----------------
 1 file changed, 73 insertions(+), 60 deletions(-)

diff --git a/sys/src/cmd/aux/vga/edid.c b/sys/src/cmd/aux/vga/edid.c
index d475678fe..09a0acbbc 100644
--- a/sys/src/cmd/aux/vga/edid.c
+++ b/sys/src/cmd/aux/vga/edid.c
@@ -6,8 +6,8 @@
 #include "pci.h"
 #include "vga.h"
 
-static Modelist*
-addmode(Modelist *l, Mode m)
+static void
+addmode(Modelist **l, Mode m)
 {
 	Modelist *ll;
 	int rr;
@@ -15,17 +15,15 @@ addmode(Modelist *l, Mode m)
 	rr = (m.frequency+m.ht*m.vt/2)/(m.ht*m.vt);
 	snprint(m.name, sizeof m.name, "%dx%d@%dHz", m.x, m.y, rr);
 
-	for(ll = l; ll != nil; ll = ll->next){
-		if(strcmp(ll->name, m.name) == 0){
-			ll->Mode = m;
-			return l;
-		}
+	for(ll = *l; ll != nil; ll = *l){
+		if(strcmp(ll->name, m.name) == 0)
+			return;
+		l = &ll->next;
 	}
 
 	ll = alloc(sizeof(Modelist));
 	ll->Mode = m;
-	ll->next = l;
-	return ll;
+	*l = ll;
 }
 
 /*
@@ -282,70 +280,85 @@ parseedid128(void *v)
 
 	assert(p == (uchar*)v+8+10+2+5+10);
 	/*
-	 * Established timings: a bitmask of 19 preset timings.
+	 * Timing information priority order (EDID 1.3 section 5)
+	 *   1. Preferred Timing Mode (first detailed timing block)
+	 *   2. Other Detailed Timing Mode, in order listed
+	 *   3. Standard Timings, in order listed
+	 *   4. Established Timings
 	 */
-	estab = (p[0]<<16) | (p[1]<<8) | p[2];
-	p += 3;
 
-	for(i=0, m=1<<23; i<nelem(estabtime); i++, m>>=1)
-		if(estab & m)
-			if(vesalookup(&mode, estabtime[i]) == 0)
-				e->modelist = addmode(e->modelist,  mode);
+	/*
+	 * Detailed Timings
+	 */
+	p = (uchar*)v+8+10+2+5+10+3+16;
+	for(i=0; i<4; i++, p+=18)
+		if(p[0] || p[1])	/* detailed timing block: p[0] or p[1] != 0 */
+			if(decodedtb(&mode, p) == 0)
+				addmode(&e->modelist, mode);
+	assert(p == (uchar*)v+8+10+2+5+10+3+16+72);
 
-	assert(p == (uchar*)v+8+10+2+5+10+3);
 	/*
 	 * Standard Timing Identifications: eight 2-byte selectors
 	 * of more standard timings.
 	 */
-
+	p = (uchar*)v+8+10+2+5+10+3;
 	for(i=0; i<8; i++, p+=2)
 		if(decodesti(&mode, p+2*i) == 0)
-			e->modelist = addmode(e->modelist, mode);
-
+			addmode(&e->modelist, mode);
 	assert(p == (uchar*)v+8+10+2+5+10+3+16);
-	/*
-	 * Detailed Timings
-	 */
-	for(i=0; i<4; i++, p+=18) {
-		if(p[0] || p[1]) {	/* detailed timing block: p[0] or p[1] != 0 */
-			if(decodedtb(&mode, p) == 0)
-				e->modelist = addmode(e->modelist, mode);
-		} else if(p[2]==0) {	/* monitor descriptor block */
-			switch(p[3]) {
-			case 0xFF:	/* monitor serial number (13-byte ascii, 0A terminated) */
-				if(q = memchr(p+5, 0x0A, 13))
-					*q = '\0';
-				memset(e->serialstr, 0, sizeof(e->serialstr));
-				strncpy(e->serialstr, (char*)p+5, 13);
-				break;
-			case 0xFE:	/* ascii string (13-byte ascii, 0A terminated) */
-				break;
-			case 0xFD:	/* monitor range limits */
-				e->rrmin = p[5];
-				e->rrmax = p[6];
-				e->hrmin = p[7]*1000;
-				e->hrmax = p[8]*1000;
-				if(p[9] != 0xFF)
-					e->pclkmax = p[9]*10*1000000;
-				break;
-			case 0xFC:	/* monitor name (13-byte ascii, 0A terminated) */
-				if(q = memchr(p+5, 0x0A, 13))
-					*q = '\0';
-				memset(e->name, 0, sizeof(e->name));
-				strncpy(e->name, (char*)p+5, 13);
-				break;
-			case 0xFB:	/* extra color point data */
-				break;
-			case 0xFA:	/* extra standard timing identifications */
-				for(i=0; i<6; i++)
-					if(decodesti(&mode, p+5+2*i) == 0)
-						e->modelist = addmode(e->modelist, mode);
-				break;
-			}
+
+	p = (uchar*)v+8+10+2+5+10+3+16;
+	for(i=0; i<4; i++, p+=18){
+		if(p[0] || p[1])
+			continue;
+		/* monitor descriptor block */
+		switch(p[3]) {
+		case 0xFF:	/* monitor serial number (13-byte ascii, 0A terminated) */
+			if(q = memchr(p+5, 0x0A, 13))
+				*q = '\0';
+			memset(e->serialstr, 0, sizeof(e->serialstr));
+			strncpy(e->serialstr, (char*)p+5, 13);
+			break;
+		case 0xFE:	/* ascii string (13-byte ascii, 0A terminated) */
+			break;
+		case 0xFD:	/* monitor range limits */
+			e->rrmin = p[5];
+			e->rrmax = p[6];
+			e->hrmin = p[7]*1000;
+			e->hrmax = p[8]*1000;
+			if(p[9] != 0xFF)
+				e->pclkmax = p[9]*10*1000000;
+			break;
+		case 0xFC:	/* monitor name (13-byte ascii, 0A terminated) */
+			if(q = memchr(p+5, 0x0A, 13))
+				*q = '\0';
+			memset(e->name, 0, sizeof(e->name));
+			strncpy(e->name, (char*)p+5, 13);
+			break;
+		case 0xFB:	/* extra color point data */
+			break;
+		case 0xFA:	/* extra standard timing identifications */
+			for(i=0; i<6; i++)
+				if(decodesti(&mode, p+5+2*i) == 0)
+					addmode(&e->modelist, mode);
+			break;
 		}
 	}
-
 	assert(p == (uchar*)v+8+10+2+5+10+3+16+72);
+
+	/*
+	 * Established timings: a bitmask of 19 preset timings.
+	 */
+	p = (uchar*)v+8+10+2+5+10;
+	estab = (p[0]<<16) | (p[1]<<8) | p[2];
+	p += 3;
+
+	for(i=0, m=1<<23; i<nelem(estabtime); i++, m>>=1)
+		if(estab & m)
+			if(vesalookup(&mode, estabtime[i]) == 0)
+				addmode(&e->modelist, mode);
+	assert(p == (uchar*)v+8+10+2+5+10+3);
+
 	return e;
 }
 
-- 
2.34.1


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [9front] [PATCH] aux/vga: return modes according to EDID timing priority order
  2022-02-28 21:20 [9front] [PATCH] aux/vga: return modes according to EDID timing priority order Michael Forney
@ 2022-02-28 22:06 ` Steve Simon
  0 siblings, 0 replies; 2+ messages in thread
From: Steve Simon @ 2022-02-28 22:06 UTC (permalink / raw)
  To: 9front

kudos for this work.


> On 28 Feb 2022, at 9:29 pm, Michael Forney <mforney@mforney.org> wrote:
> 
> 
> EDID 1.3 section 5 gives a table describing the priority order of
> timing information. Use this ordering when constructing the EDID
> mode list.
> 
> Since aux/vga selects the first mode in the modelist that matches
> the given size, it will now select the mode of that size with the
> highest preference. Or, if you set vgasize=auto (or some other
> string without an 'x'), aux/vga will select the Preferred Detailed
> Timing.
> 
> This should make it unnecessary to modify vgadb in many cases.
> ---
> sys/src/cmd/aux/vga/edid.c | 133 ++++++++++++++++++++-----------------
> 1 file changed, 73 insertions(+), 60 deletions(-)
> 
> diff --git a/sys/src/cmd/aux/vga/edid.c b/sys/src/cmd/aux/vga/edid.c
> index d475678fe..09a0acbbc 100644
> --- a/sys/src/cmd/aux/vga/edid.c
> +++ b/sys/src/cmd/aux/vga/edid.c
> @@ -6,8 +6,8 @@
> #include "pci.h"
> #include "vga.h"
> 
> -static Modelist*
> -addmode(Modelist *l, Mode m)
> +static void
> +addmode(Modelist **l, Mode m)
> {
>    Modelist *ll;
>    int rr;
> @@ -15,17 +15,15 @@ addmode(Modelist *l, Mode m)
>    rr = (m.frequency+m.ht*m.vt/2)/(m.ht*m.vt);
>    snprint(m.name, sizeof m.name, "%dx%d@%dHz", m.x, m.y, rr);
> 
> -    for(ll = l; ll != nil; ll = ll->next){
> -        if(strcmp(ll->name, m.name) == 0){
> -            ll->Mode = m;
> -            return l;
> -        }
> +    for(ll = *l; ll != nil; ll = *l){
> +        if(strcmp(ll->name, m.name) == 0)
> +            return;
> +        l = &ll->next;
>    }
> 
>    ll = alloc(sizeof(Modelist));
>    ll->Mode = m;
> -    ll->next = l;
> -    return ll;
> +    *l = ll;
> }
> 
> /*
> @@ -282,70 +280,85 @@ parseedid128(void *v)
> 
>    assert(p == (uchar*)v+8+10+2+5+10);
>    /*
> -     * Established timings: a bitmask of 19 preset timings.
> +     * Timing information priority order (EDID 1.3 section 5)
> +     *   1. Preferred Timing Mode (first detailed timing block)
> +     *   2. Other Detailed Timing Mode, in order listed
> +     *   3. Standard Timings, in order listed
> +     *   4. Established Timings
>     */
> -    estab = (p[0]<<16) | (p[1]<<8) | p[2];
> -    p += 3;
> 
> -    for(i=0, m=1<<23; i<nelem(estabtime); i++, m>>=1)
> -        if(estab & m)
> -            if(vesalookup(&mode, estabtime[i]) == 0)
> -                e->modelist = addmode(e->modelist,  mode);
> +    /*
> +     * Detailed Timings
> +     */
> +    p = (uchar*)v+8+10+2+5+10+3+16;
> +    for(i=0; i<4; i++, p+=18)
> +        if(p[0] || p[1])    /* detailed timing block: p[0] or p[1] != 0 */
> +            if(decodedtb(&mode, p) == 0)
> +                addmode(&e->modelist, mode);
> +    assert(p == (uchar*)v+8+10+2+5+10+3+16+72);
> 
> -    assert(p == (uchar*)v+8+10+2+5+10+3);
>    /*
>     * Standard Timing Identifications: eight 2-byte selectors
>     * of more standard timings.
>     */
> -
> +    p = (uchar*)v+8+10+2+5+10+3;
>    for(i=0; i<8; i++, p+=2)
>        if(decodesti(&mode, p+2*i) == 0)
> -            e->modelist = addmode(e->modelist, mode);
> -
> +            addmode(&e->modelist, mode);
>    assert(p == (uchar*)v+8+10+2+5+10+3+16);
> -    /*
> -     * Detailed Timings
> -     */
> -    for(i=0; i<4; i++, p+=18) {
> -        if(p[0] || p[1]) {    /* detailed timing block: p[0] or p[1] != 0 */
> -            if(decodedtb(&mode, p) == 0)
> -                e->modelist = addmode(e->modelist, mode);
> -        } else if(p[2]==0) {    /* monitor descriptor block */
> -            switch(p[3]) {
> -            case 0xFF:    /* monitor serial number (13-byte ascii, 0A terminated) */
> -                if(q = memchr(p+5, 0x0A, 13))
> -                    *q = '\0';
> -                memset(e->serialstr, 0, sizeof(e->serialstr));
> -                strncpy(e->serialstr, (char*)p+5, 13);
> -                break;
> -            case 0xFE:    /* ascii string (13-byte ascii, 0A terminated) */
> -                break;
> -            case 0xFD:    /* monitor range limits */
> -                e->rrmin = p[5];
> -                e->rrmax = p[6];
> -                e->hrmin = p[7]*1000;
> -                e->hrmax = p[8]*1000;
> -                if(p[9] != 0xFF)
> -                    e->pclkmax = p[9]*10*1000000;
> -                break;
> -            case 0xFC:    /* monitor name (13-byte ascii, 0A terminated) */
> -                if(q = memchr(p+5, 0x0A, 13))
> -                    *q = '\0';
> -                memset(e->name, 0, sizeof(e->name));
> -                strncpy(e->name, (char*)p+5, 13);
> -                break;
> -            case 0xFB:    /* extra color point data */
> -                break;
> -            case 0xFA:    /* extra standard timing identifications */
> -                for(i=0; i<6; i++)
> -                    if(decodesti(&mode, p+5+2*i) == 0)
> -                        e->modelist = addmode(e->modelist, mode);
> -                break;
> -            }
> +
> +    p = (uchar*)v+8+10+2+5+10+3+16;
> +    for(i=0; i<4; i++, p+=18){
> +        if(p[0] || p[1])
> +            continue;
> +        /* monitor descriptor block */
> +        switch(p[3]) {
> +        case 0xFF:    /* monitor serial number (13-byte ascii, 0A terminated) */
> +            if(q = memchr(p+5, 0x0A, 13))
> +                *q = '\0';
> +            memset(e->serialstr, 0, sizeof(e->serialstr));
> +            strncpy(e->serialstr, (char*)p+5, 13);
> +            break;
> +        case 0xFE:    /* ascii string (13-byte ascii, 0A terminated) */
> +            break;
> +        case 0xFD:    /* monitor range limits */
> +            e->rrmin = p[5];
> +            e->rrmax = p[6];
> +            e->hrmin = p[7]*1000;
> +            e->hrmax = p[8]*1000;
> +            if(p[9] != 0xFF)
> +                e->pclkmax = p[9]*10*1000000;
> +            break;
> +        case 0xFC:    /* monitor name (13-byte ascii, 0A terminated) */
> +            if(q = memchr(p+5, 0x0A, 13))
> +                *q = '\0';
> +            memset(e->name, 0, sizeof(e->name));
> +            strncpy(e->name, (char*)p+5, 13);
> +            break;
> +        case 0xFB:    /* extra color point data */
> +            break;
> +        case 0xFA:    /* extra standard timing identifications */
> +            for(i=0; i<6; i++)
> +                if(decodesti(&mode, p+5+2*i) == 0)
> +                    addmode(&e->modelist, mode);
> +            break;
>        }
>    }
> -
>    assert(p == (uchar*)v+8+10+2+5+10+3+16+72);
> +
> +    /*
> +     * Established timings: a bitmask of 19 preset timings.
> +     */
> +    p = (uchar*)v+8+10+2+5+10;
> +    estab = (p[0]<<16) | (p[1]<<8) | p[2];
> +    p += 3;
> +
> +    for(i=0, m=1<<23; i<nelem(estabtime); i++, m>>=1)
> +        if(estab & m)
> +            if(vesalookup(&mode, estabtime[i]) == 0)
> +                addmode(&e->modelist, mode);
> +    assert(p == (uchar*)v+8+10+2+5+10+3);
> +
>    return e;
> }
> 
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-02-28 22:32 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-28 21:20 [9front] [PATCH] aux/vga: return modes according to EDID timing priority order Michael Forney
2022-02-28 22:06 ` Steve Simon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).