>From cb00e6fade39afdb2adb0727647e9c97ce0fd02c Mon Sep 17 00:00:00 2001
From: David Kozub <zub@linux.fjfi.cvut.cz>
Date: Thu, 7 Jun 2012 15:46:16 +0200
Subject: [PATCH] add support for custom sync flags

---
 fb.modes.5 |    3 +++
 fbset.8    |    4 ++++
 fbset.c    |   45 +++++++++++++++++++++++++++++++++++++++++++++
 fbset.h    |    3 +++
 modes.l    |    3 ++-
 modes.y    |   10 +++++++++-
 6 files changed, 66 insertions(+), 2 deletions(-)

--- a/fb.modes.5
+++ b/fb.modes.5
@@ -120,6 +120,9 @@ generated by the frame buffer device and
 instead. Note that this option may not be supported by every frame buffer
 device
 .TP
+.IR \fBsync "\ <" number >
+custom sync flags (frame buffer driver dependent)
+.TP
 .IR \fBlaced "\ {" false | true }
 enable or disable interlace. If enabled the display will be split in two
 frames, each frame contains only even and odd lines respectively. These two
--- a/fbset.8
+++ b/fbset.8
@@ -191,6 +191,10 @@ generated by the frame buffer device and
 instead. Note that this option may not be supported by every frame buffer
 device
 .TP
+.IR \fB\-sync "\ <" \fIvalue >
+set custom sync flags. If specified, this value is bitwise or-ed to the
+other sync flags. This is useful for drivers that use custom sync flags
+.TP
 .IR \fB\-bcast "\ {" false | true }
 enable or disable broadcast modes. If enabled the frame buffer generates the
 exact timings for several broadcast modes (e.g. PAL or NTSC). Note that
--- a/fbset.c
+++ b/fbset.c
@@ -16,6 +16,9 @@
  *  Brad Midgley <brad@exodus.pht.com>:
  *           -match
  *
+ *  David Kozub <zub@linux.fjfi.cvut.cz>:
+ *           -sync
+ *
  */
 
 
@@ -52,6 +55,12 @@ struct inode;
 
 
     /*
+     *  Mask to zero-out all known sync flags
+     */
+#define FB_CUSTOM_SYNC_MASK ~(FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT| \
+    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_ON_GREEN|FB_SYNC_EXT|FB_SYNC_BROADCAST)
+
+    /*
      *  Command Line Options
      */
 
@@ -86,6 +95,7 @@ static const char *Opt_vsync = NULL;
 static const char *Opt_csync = NULL;
 static const char *Opt_gsync = NULL;
 static const char *Opt_extsync = NULL;
+static const char *Opt_sync = NULL;
 static const char *Opt_bcast = NULL;
 static const char *Opt_laced = NULL;
 static const char *Opt_double = NULL;
@@ -123,6 +133,7 @@ static struct {
     { "-csync", &Opt_csync, 1 },
     { "-gsync", &Opt_gsync, 1 },
     { "-extsync", &Opt_extsync, 1 },
+    { "-sync", &Opt_sync, 1 },
     { "-bcast", &Opt_bcast, 1 },
     { "-laced", &Opt_laced, 1 },
     { "-double", &Opt_double, 1 },
@@ -402,6 +413,7 @@ static void ConvertFromVideoMode(const s
 	var->sync |= FB_SYNC_EXT;
     if (vmode->bcast == TRUE)
 	var->sync |= FB_SYNC_BROADCAST;
+    var->sync |= vmode->sync;
     if (vmode->laced == TRUE)
 	var->vmode = FB_VMODE_INTERLACED;
     else if (vmode->dblscan == TRUE)
@@ -445,6 +457,7 @@ static void ConvertToVideoMode(const str
     vmode->gsync = var->sync & FB_SYNC_ON_GREEN ? TRUE : FALSE;
     vmode->extsync = var->sync & FB_SYNC_EXT ? TRUE : FALSE;
     vmode->bcast = var->sync & FB_SYNC_BROADCAST ? TRUE : FALSE;
+    vmode->sync = var->sync & FB_CUSTOM_SYNC_MASK;
     vmode->grayscale = var->grayscale;
     vmode->laced = FALSE;
     vmode->dblscan = FALSE;
@@ -554,6 +567,27 @@ void makeRGBA(struct VideoMode *vmode, c
 }
 
     /*
+     *  Take known bits from sync and set appropriate flags instead
+     */
+
+void fixCustomSync(struct VideoMode *vmode)
+{
+    if (vmode->sync & FB_SYNC_HOR_HIGH_ACT)
+	vmode->hsync = 1;
+    if (vmode->sync & FB_SYNC_VERT_HIGH_ACT)
+	vmode->vsync = 1;
+    if (vmode->sync & FB_SYNC_COMP_HIGH_ACT)
+	vmode->csync = 1;
+    if (vmode->sync & FB_SYNC_ON_GREEN)
+	vmode->gsync = 1;
+    if (vmode->sync & FB_SYNC_EXT)
+	vmode->extsync =1;
+    if (vmode->sync & FB_SYNC_BROADCAST)
+	vmode->bcast = 1;
+    vmode->sync &= FB_CUSTOM_SYNC_MASK;
+}
+
+    /*
      *  Find a Video Mode
      */
 
@@ -617,6 +651,12 @@ static void ModifyVideoMode(struct Video
 	vmode->extsync = atoboolean(Opt_extsync);
     if (Opt_bcast)
 	vmode->bcast = atoboolean(Opt_bcast);
+    if (Opt_sync)
+    {
+	vmode->sync = strtoul(Opt_sync, NULL, 0);
+	// call this only once all the other sync fields are determined!
+	fixCustomSync(vmode);
+    }
     if (Opt_laced)
 	vmode->laced = atoboolean(Opt_laced);
     if (Opt_double)
@@ -693,6 +733,8 @@ static void DisplayVModeInfo(struct Vide
 	    puts("    extsync true");
 	if (vmode->bcast)
 	    puts("    bcast true");
+	if (vmode->sync)
+	    printf("    sync 0x%x\n", vmode->sync);
 	if (vmode->laced)
 	    puts("    laced true");
 	if (vmode->dblscan)
@@ -745,6 +787,8 @@ static void DisplayVModeInfo(struct Vide
 	    puts("    # Warning: XFree86 doesn't support extsync\n");
 	if (vmode->bcast)
 	    printf(" \"bcast\"");
+	if (vmode->sync)
+	    puts("    # Warning: XFree86 doesn't support custom sync values\n");
 	if (vmode->accel_flags)
 	    puts("    # Warning: XFree86 doesn't support accel\n");
 	if (vmode->grayscale)
@@ -931,6 +975,7 @@ static void Usage(void)
 	"    -csync <value>     : composite sync polarity (low or high)\n"
 	"    -gsync <value>     : synch on green (false or true)\n"
 	"    -extsync <value>   : external sync enable (false or true)\n"
+	"    -sync <value>      : custom (driver specific) sync value\n"
 	"    -bcast <value>     : broadcast enable (false or true)\n"
 	"    -laced <value>     : interlace enable (false or true)\n"
 	"    -double <value>    : doublescan enable (false or true)\n"
--- a/fbset.h
+++ b/fbset.h
@@ -64,6 +64,8 @@ struct VideoMode {
     unsigned laced : 1;
     unsigned dblscan : 1;
     unsigned grayscale : 1;
+    /* extra (fb driver specific) sync bits */
+    __u32 sync;
     /* scanrates */
     double drate;
     double hrate;
@@ -80,3 +82,4 @@ extern int yyparse(void);
 extern void Die(const char *fmt, ...) __attribute__ ((noreturn));
 extern void AddVideoMode(const struct VideoMode *vmode);
 extern void makeRGBA(struct VideoMode *vmode, const char* opt);
+extern void fixCustomSync(struct VideoMode *vmode);
--- a/modes.l
+++ b/modes.l
@@ -38,6 +38,7 @@ static struct keyword keywords[] = {
     { "csync", CSYNC, 0 },
     { "gsync", GSYNC, 0 },
     { "extsync", EXTSYNC, 0 },
+    { "sync", SYNC, 0 },
     { "bcast", BCAST, 0 },
     { "laced", LACED, 0 },
     { "double", DOUBLE, 0 },
@@ -98,7 +99,7 @@ static const char *CopyString(const char
 %}
 
 keyword	[a-zA-Z][a-zA-Z0-9]*
-number	[0-9]*
+number	(0x)?[0-9]*
 colors	[0-9/,]*
 string	\"[^\"\n]*\"
 comment	\#([^\n]*)
--- a/modes.y
+++ b/modes.y
@@ -40,7 +40,7 @@ static void ClearVideoMode(void)
 
 %start file
 
-%token MODE GEOMETRY TIMINGS HSYNC VSYNC CSYNC GSYNC EXTSYNC BCAST LACED DOUBLE
+%token MODE GEOMETRY TIMINGS HSYNC VSYNC CSYNC GSYNC EXTSYNC SYNC BCAST LACED DOUBLE
        RGBA NONSTD ACCEL GRAYSCALE
        ENDMODE POLARITY BOOLEAN STRING NUMBER COLORS
 
@@ -91,6 +91,7 @@ options	  : /* empty */
 	  | options csync
 	  | options gsync
 	  | options extsync
+	  | options sync
 	  | options bcast
 	  | options laced
 	  | options double
@@ -130,6 +131,13 @@ extsync	  : EXTSYNC BOOLEAN
 	    }
 	  ;
 
+sync: SYNC NUMBER
+	    {
+		VideoMode.sync = $2;
+		fixCustomSync(&VideoMode);
+	    }
+	  ;
+
 bcast	  : BCAST BOOLEAN
 	    {
 		VideoMode.bcast = $2;
