--- a/glcddrivers/Makefile
+++ b/glcddrivers/Makefile
@@ -63,6 +63,11 @@
     LIBS += -lwiringPi
 endif
 
+ifeq ($(HAVE_DRIVER_VUPLUS4K), 1)
+    DEFINES += -DHAVE_DRIVER_VUPLUS4K
+    OBJS += vuplus4k.o
+endif
+
 ### Implicit rules:
 
 %.o: %.c
--- a/glcddrivers/drivers.c
+++ b/glcddrivers/drivers.c
@@ -50,6 +50,9 @@
 #ifdef HAVE_DRIVER_ILI9341
 #include "ili9341.h"
 #endif
+#ifdef HAVE_DRIVER_VUPLUS4K
+#include "vuplus4k.h"
+#endif
 
 namespace GLCD
 {
@@ -93,6 +96,9 @@
 #endif
 #ifdef HAVE_DRIVER_ILI9341
     {"ili9341",       kDriverILI9341},
+#endif
+#ifdef HAVE_DRIVER_VUPLUS4K
+    {"vuplus4k",      kDriverVUPLUS4K},
 #endif
     {"",              kDriverUnknown}
 };
@@ -180,6 +186,10 @@
         case kDriverILI9341:
             return new cDriverILI9341(config);
 #endif
+#ifdef HAVE_DRIVER_VUPLUS4K
+        case kDriverVUPLUS4K:
+            return new cDriverVUPLUS4K(config);
+#endif
         case kDriverUnknown:
         default:
             return NULL;
--- a/glcddrivers/driver.h
+++ b/glcddrivers/driver.h
@@ -74,7 +74,7 @@ public:
     virtual void Refresh(bool refreshAll = false) {}
 
     virtual void SetBrightness(unsigned int percent) {}
-
+    virtual void SetMirrorVideo(bool mirror) {}
 
     virtual bool SetFeature  (const std::string & Feature, int value)   { return false; }
 
--- a/glcddrivers/drivers.h
+++ b/glcddrivers/drivers.h
@@ -58,6 +58,9 @@
 #endif
     kDriverUSBserLCD     = 23,
     kDriverST7565RReel   = 24,
+#ifdef HAVE_DRIVER_VUPLUS4K
+    kDriverVUPLUS4K      = 25,
+#endif
     kDriverSerDisp       = 100,
     kDriverG15daemon     = 200
 };
--- /dev/null
+++ b/glcddrivers/vuplus4k.c
@@ -0,0 +1,282 @@
+/*
+ * GraphLCD driver library
+ *
+ * vuplus4k.c  -  VUPLUS4K OLED driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) redblue 2019
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <stdint.h>
+#include <syslog.h>
+#include <cstring>
+#include <byteswap.h>
+
+#include "common.h"
+#include "config.h"
+#include "vuplus4k.h"
+
+namespace GLCD
+{
+
+cDriverVUPLUS4K::cDriverVUPLUS4K(cDriverConfig * config)
+:	cDriver(config),
+	fd(-1)
+{
+}
+
+cDriverVUPLUS4K::~cDriverVUPLUS4K()
+{
+	DeInit();
+}
+
+int lcd_read_value(const char *filename)
+{
+	int value = 0;
+	FILE *fd = fopen(filename, "r");
+	if (fd) {
+		int tmp;
+		if (fscanf(fd, "%x", &tmp) == 1)
+			value = tmp;
+		fclose(fd);
+	}
+	return value;
+}
+
+int cDriverVUPLUS4K::Init()
+{
+	int x;
+
+	width = config->width;
+	if (width <= 0)
+		width = lcd_read_value(XRES);
+
+	height = config->height;
+	if (height <= 0)
+		height = lcd_read_value(YRES);
+
+	bpp = lcd_read_value(BPP);
+
+	switch (bpp)
+	{
+		case 8:
+			stride_bpp_value = 1;
+			break;
+		case 15:
+		case 16:
+			stride_bpp_value = 2;
+			break;
+		case 24:
+		case 32:
+			stride_bpp_value = 4;
+			break;
+		default:
+			stride_bpp_value = (bpp + 7) / 8;
+	}
+
+	stride = width * stride_bpp_value;
+
+	for (unsigned int i = 0; i < config->options.size(); i++)
+	{
+		if (config->options[i].name == "")
+		{
+		}
+	}
+
+	if (config->device == "")
+	{
+		fd = open("/dev/dbox/lcd0", O_RDWR);
+		if (fd == -1)
+			fd = open("/dev/lcd0", O_RDWR);
+		if (fd == -1)
+			fd = open("/dev/dbox/oled0", O_RDWR);
+		if (fd == -1)
+			fd = open("/dev/oled0", O_RDWR);
+	}
+	else
+	{
+		fd = open(config->device.c_str(), O_RDWR);
+	}
+
+	if (fd == -1) {
+		printf("cannot open lcd device\n");
+		return -1;
+	}
+
+	int tmp = LCD_MODE_BIN;
+	if (ioctl(fd, LCD_IOCTL_ASC_MODE, &tmp)) {
+		printf("failed to set lcd bin mode\n");
+	}
+
+	newLCD = new uint16_t[height * stride];
+	if (newLCD)
+		memset(newLCD, 0, height * stride);
+	oldLCD = new uint16_t[height * stride];
+	if (oldLCD)
+		memset(oldLCD, 0, height * stride);
+
+	syslog(LOG_INFO, "%s: current lcd is %dx%d, %dbpp, vuplus4k lcd device was opened successfully\n", config->name.c_str(), width, height, bpp);
+
+	*oldConfig = *config;
+
+	// clear display
+	Clear();
+	//Refresh(true);
+
+	syslog(LOG_INFO, "%s: VUPLUS4K initialized.\n", config->name.c_str());
+	return 0;
+}
+
+int cDriverVUPLUS4K::DeInit()
+{
+	if (newLCD)
+	{
+		delete[] newLCD;
+		newLCD = 0;
+	}
+	if (oldLCD)
+	{
+		delete[] oldLCD;
+		oldLCD = 0;
+	}
+	if (-1 != fd)
+	{
+        	close(fd);
+		fd=-1;
+	}
+	return 0;
+}
+
+int cDriverVUPLUS4K::CheckSetup()
+{
+	if (config->width != oldConfig->width ||
+		config->height != oldConfig->height)
+	{
+		DeInit();
+		Init();
+		return 0;
+	}
+
+	if (config->upsideDown != oldConfig->upsideDown ||
+		config->invert != oldConfig->invert)
+	{
+		oldConfig->upsideDown = config->upsideDown;
+		oldConfig->invert = config->invert;
+		return 1;
+	}
+	return 0;
+}
+
+void cDriverVUPLUS4K::Clear()
+{
+	memset(newLCD, 0, width * height);
+}
+
+void cDriverVUPLUS4K::SetPixel(int x, int y, uint32_t data)
+{
+	if (x >= width || y >= height)
+		return;
+
+	if (config->upsideDown)
+	{
+		x = width - 1 - x;
+		y = height - 1 - y;
+	}
+
+	uint32_t red, green, blue;
+	blue = (data & 0x000000FF) >> 0;
+	green = (data & 0x0000FF00) >> 8;
+	red = (data & 0x00FF0000) >> 16;
+
+	unsigned char* row_pointers_bit_shift = (unsigned char*) &newLCD[0];
+	int row_pointers_2_ptr = (y * width + x) * stride_bpp_value;
+
+ 	if (config->invert) {
+		blue = 255 - blue;
+		green = 255 - green;
+		red = 255 - red;
+	}
+
+	row_pointers_bit_shift[row_pointers_2_ptr+0]=blue;
+	row_pointers_bit_shift[row_pointers_2_ptr+1]=green;
+	row_pointers_bit_shift[row_pointers_2_ptr+2]=red;
+	row_pointers_bit_shift[row_pointers_2_ptr+3]=0xff;
+}
+
+void cDriverVUPLUS4K::Refresh(bool refreshAll)
+{
+	int i;
+	char fileName[256];
+	char str[32];
+	FILE * fp;
+	unsigned char c;
+
+	if (CheckSetup() > 0)
+		refreshAll = true;
+
+	for (i = 0; i < height * stride; i++)
+	{
+		if (newLCD[i] != oldLCD[i])
+		{
+			refreshAll = true;
+			break;
+		}
+	}
+
+	if (refreshAll)
+	{
+		for (i = 0; i < height * stride; i++)
+		{
+			oldLCD[i] = newLCD[i];
+		}
+		unsigned char* row_pointers_bit_shift = (unsigned char*) &newLCD[0];
+		{
+			write(fd, row_pointers_bit_shift, height * stride);
+		}
+	}
+}
+
+void cDriverVUPLUS4K::SetBrightness(unsigned int brightness)
+{
+	int value = 0;
+	value = 255 * brightness / 10;
+
+	FILE *f = fopen("/proc/stb/lcd/oled_brightness", "w");
+	if (!f)
+		f = fopen("/proc/stb/fp/oled_brightness", "w");
+	if (f)
+	{
+		if (fprintf(f, "%d", value) == 0)
+			printf("write /proc/stb/lcd/oled_brightness failed!! (%m)\n");
+		fclose(f);
+	}
+}
+
+void cDriverVUPLUS4K::SetMirrorVideo(bool mirror)
+{
+	const char *value = "";
+
+	if (mirror)
+		value = "enable";
+	else
+		value = "disable";
+
+	FILE *f = fopen("/proc/stb/lcd/live_enable", "w");
+	if (f)
+	{
+		if (fprintf(f, "%s", value) == 0)
+			printf("write /proc/stb/lcd/live_enable failed!! (%m)\n");
+		fclose(f);
+	}
+}
+
+} // end of namespace
--- /dev/null
+++ b/glcddrivers/vuplus4k.h
@@ -0,0 +1,65 @@
+/*
+ * GraphLCD driver library
+ *
+ * vuplus4k.c  -  VUPLUS4K OLED driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) redblue
+ */
+
+
+#ifndef _GLCDDRIVERS_VUPLUS4K_H_
+#define _GLCDDRIVERS_VUPLUS4K_H_
+
+#include "driver.h"
+
+namespace GLCD
+{
+
+#define XRES "/proc/stb/lcd/xres"
+#define YRES "/proc/stb/lcd/yres"
+#define BPP "/proc/stb/lcd/bpp"
+
+#ifndef LCD_IOCTL_ASC_MODE
+#define LCDSET                          0x1000
+#define LCD_IOCTL_ASC_MODE              (21|LCDSET)
+#define LCD_MODE_ASC                    0
+#define LCD_MODE_BIN                    1
+#endif
+
+#define FP_IOCTL_LCD_DIMM       3
+
+class cDriverConfig;
+
+class cDriverVUPLUS4K : public cDriver
+{
+private:
+	int fd;
+	uint16_t * newLCD;
+	uint16_t * oldLCD;
+	int bpp;
+	int stride;
+	int stride_bpp_value;
+
+	int CheckSetup();
+
+public:
+	cDriverVUPLUS4K(cDriverConfig * config);
+	virtual ~cDriverVUPLUS4K();
+
+	virtual int Init();
+	virtual int DeInit();
+
+	virtual void Clear();
+	virtual void SetPixel(int x, int y, uint32_t data);
+	//virtual void Set8Pixels(int x, int y, unsigned char data);
+	virtual void Refresh(bool refreshAll = false);
+	virtual void SetBrightness(unsigned int percent);
+	virtual void SetMirrorVideo(bool mirror);
+};
+
+} // end of namespace
+
+#endif
--- a/Make.config
+++ b/Make.config
@@ -83,3 +83,6 @@
 #HAVE_DRIVER_SSD1306=1
 
 #HAVE_DRIVER_ILI9341=1
+
+# uncomment this variable if you want to enable the experimental support for vuplus4k
+HAVE_DRIVER_VUPLUS4K=1
--- a/README
+++ b/README
@@ -28,6 +28,7 @@
     futaba md166 driver by     Andreas Brachold <vdr07 AT deltab de>
     usbserlcd driver by        Manuel Reimer <manuel.reimer AT gmx.de>
     st7565r-reel driver by     Georg Acher, BayCom GmbH based on simlcd.c by Carsten Siebholz, ported by Ufuk Altinkaynak
+    vuplus4k oled driver by    redblue <redblue.pkt at orange pl>
 
 Project's homepage: https://projects.vdr-developer.org/projects/graphlcd-base
 GIT repo: https://projects.vdr-developer.org/git/graphlcd-base.git
--- a/graphlcd.conf
+++ b/graphlcd.conf
@@ -117,6 +117,14 @@
 
 ########################################################################
 
+[vuplus4k]
+#  Driver setting for the OLED VUPLUS4K
+Driver=vuplus4k
+#Width=480
+#Height=320
+
+########################################################################
+
 [ax206dpf]
 #  THIS IS AN EXPERIMENTAL DRIVER!
 #  You have to uncomment the variable HAVE_DRIVER_AX206DPF