All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support
@ 2016-01-05 16:30 Simon Glass
  2016-01-05 16:30 ` [U-Boot] [PATCH 01/18] tiny-printf: Always print zeroes Simon Glass
                   ` (18 more replies)
  0 siblings, 19 replies; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:30 UTC (permalink / raw)
  To: u-boot

This series starts the process of converting LCD and video devices over to
use driver model. Both now use a very similar API thanks to earlier work by
Nikita Kiryanov. With the driver-model conversion these will end up unified
in a single uclass.

Unfortunately there are different features supported by each. This
implementation provides for a common set of features which should serve
most purposes. The intent is to support:

- bitmap devices with 8, 16 and 32 bits per pixel
- text console wih white on black or vice versa
- rotated text console
- bitmap display (BMP format)

More can be added as additional boards are ported over to use driver model
for video.

The name 'video' is chosen for the uclass since it is more generic than LCD.
Another option would be 'display' but that would introduce a third concept
to U-Boot which seems like the wrong approach.

The existing LCD and video init functions are not needed now, so this uclass
does not implement them. This includes lcd_ctrl_init(), lcd_enable() and
video_init().

Tests are provided to check that console text and bitmap output is correct.
These should be able to be extended as more features are added.

Future work will convert a few boards over to use driver model for video.
Likely targets are x86, exynos, tegra. Also, Rockchip LCD support will be
added using driver model (patches will likely be sent some time in January).


Simon Glass (18):
  tiny-printf: Always print zeroes
  sandbox: Support the bmp command
  dm: core: Call uclass post_bind() after the driver's bind() method
  bzip2: Support compression for sandbox
  dm: video: Add a video uclass
  dm: lcd: Avoid using the lcd.h header file with driver model
  dm: video: Add a uclass for the text console
  dm: video: Add a 'normal' text console driver
  dm: video: Add a driver for a rotated text console
  common: Move LCD and video memory reservation together
  dm: common: Add memory reservation for the video uclass
  dm: video: Implement the bmp command for driver model
  dm: stdio: video: Plumb the video uclass into stdio
  sandbox: Move CONFIG_VIDEO_SANDBOX_SDL to Kconfig
  dm: video: sandbox: Convert sandbox to use driver model for video
  dm: video: test: Add tests for the video uclass
  dm: video: test: Add tests for rotated consoles
  dm: video: test: Test that bitmap display works correctly

 arch/sandbox/dts/sandbox.dts      |    1 +
 arch/sandbox/dts/test.dts         |    7 +
 board/sandbox/sandbox.c           |   17 -
 common/Makefile                   |    2 +
 common/board_f.c                  |   71 ++-
 common/cmd_bmp.c                  |   37 +-
 common/lcd.c                      |   11 -
 common/stdio.c                    |   19 +-
 configs/sandbox_defconfig         |    5 +-
 drivers/core/device.c             |    7 +
 drivers/core/uclass.c             |    5 -
 drivers/serial/sandbox.c          |    5 +-
 drivers/video/Kconfig             |   62 ++
 drivers/video/Makefile            |    3 +
 drivers/video/console_normal.c    |  141 +++++
 drivers/video/console_rotate.c    |  435 ++++++++++++++
 drivers/video/sandbox_sdl.c       |   90 ++-
 drivers/video/vidconsole-uclass.c |  239 ++++++++
 drivers/video/video-uclass.c      |  249 ++++++++
 drivers/video/video_bmp.c         |  353 ++++++++++++
 include/asm-generic/global_data.h |    4 +
 include/bzlib.h                   |    3 +
 include/configs/sandbox.h         |   13 +-
 include/dm/test.h                 |    8 +
 include/dm/uclass-id.h            |    2 +
 include/fdtdec.h                  |    1 -
 include/lcd.h                     |   12 +-
 include/video.h                   |  169 +++++-
 include/video_console.h           |  136 +++++
 lib/bzip2/Makefile                |    1 +
 lib/bzip2/bzlib_blocksort.c       | 1134 +++++++++++++++++++++++++++++++++++++
 lib/bzip2/bzlib_compress.c        |  714 +++++++++++++++++++++++
 lib/fdtdec.c                      |    1 -
 lib/tiny-printf.c                 |   16 +-
 test/dm/Makefile                  |    1 +
 test/dm/video.c                   |  271 +++++++++
 tools/logos/denx-comp.bmp         |  Bin 0 -> 4148 bytes
 37 files changed, 4101 insertions(+), 144 deletions(-)
 create mode 100644 drivers/video/console_normal.c
 create mode 100644 drivers/video/console_rotate.c
 create mode 100644 drivers/video/vidconsole-uclass.c
 create mode 100644 drivers/video/video-uclass.c
 create mode 100644 drivers/video/video_bmp.c
 create mode 100644 include/video_console.h
 create mode 100644 lib/bzip2/bzlib_blocksort.c
 create mode 100644 lib/bzip2/bzlib_compress.c
 create mode 100644 test/dm/video.c
 create mode 100644 tools/logos/denx-comp.bmp

-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 01/18] tiny-printf: Always print zeroes
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
@ 2016-01-05 16:30 ` Simon Glass
  2016-01-05 17:08   ` Stefan Roese
  2016-01-13 21:55   ` Tom Rini
  2016-01-05 16:30 ` [U-Boot] [PATCH 02/18] sandbox: Support the bmp command Simon Glass
                   ` (17 subsequent siblings)
  18 siblings, 2 replies; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:30 UTC (permalink / raw)
  To: u-boot

At present this does not print zero values in numeric format (hex and
decimal). Add a special case for this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 lib/tiny-printf.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c
index efe5c25..a06abed 100644
--- a/lib/tiny-printf.c
+++ b/lib/tiny-printf.c
@@ -82,13 +82,21 @@ int vprintf(const char *fmt, va_list va)
 					num = -(int)num;
 					out('-');
 				}
-				for (div = 1000000000; div; div /= 10)
-					div_out(&num, div);
+				if (!num) {
+					out_dgt(0);
+				} else {
+					for (div = 1000000000; div; div /= 10)
+						div_out(&num, div);
+				}
 				break;
 			case 'x':
 				num = va_arg(va, unsigned int);
-				for (div = 0x10000000; div; div /= 0x10)
-					div_out(&num, div);
+				if (!num) {
+					out_dgt(0);
+				} else {
+					for (div = 0x10000000; div; div /= 0x10)
+						div_out(&num, div);
+				}
 				break;
 			case 'c':
 				out((char)(va_arg(va, int)));
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 02/18] sandbox: Support the bmp command
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
  2016-01-05 16:30 ` [U-Boot] [PATCH 01/18] tiny-printf: Always print zeroes Simon Glass
@ 2016-01-05 16:30 ` Simon Glass
  2016-01-13 21:55   ` Tom Rini
  2016-01-05 16:30 ` [U-Boot] [PATCH 03/18] dm: core: Call uclass post_bind() after the driver's bind() method Simon Glass
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:30 UTC (permalink / raw)
  To: u-boot

Adjust this command to use map_sysmem() correctly so that it works on
sandbox.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 common/cmd_bmp.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/common/cmd_bmp.c b/common/cmd_bmp.c
index cb1f071..f04b7d4 100644
--- a/common/cmd_bmp.c
+++ b/common/cmd_bmp.c
@@ -15,6 +15,7 @@
 #include <command.h>
 #include <asm/byteorder.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <splash.h>
 #include <video.h>
 
@@ -57,7 +58,8 @@ struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
 	/* align to 32-bit-aligned-address + 2 */
 	bmp = (struct bmp_image *)((((unsigned int)dst + 1) & ~3) + 2);
 
-	if (gunzip(bmp, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE, (uchar *)addr, &len) != 0) {
+	if (gunzip(bmp, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE, map_sysmem(addr, 0),
+		   &len) != 0) {
 		free(dst);
 		return NULL;
 	}
@@ -187,7 +189,7 @@ U_BOOT_CMD(
  */
 static int bmp_info(ulong addr)
 {
-	struct bmp_image *bmp = (struct bmp_image *)addr;
+	struct bmp_image *bmp = (struct bmp_image *)map_sysmem(addr, 0);
 	void *bmp_alloc_addr = NULL;
 	unsigned long len;
 
@@ -224,7 +226,7 @@ static int bmp_info(ulong addr)
 int bmp_display(ulong addr, int x, int y)
 {
 	int ret;
-	struct bmp_image *bmp = (struct bmp_image *)addr;
+	struct bmp_image *bmp = map_sysmem(addr, 0);
 	void *bmp_alloc_addr = NULL;
 	unsigned long len;
 
@@ -236,11 +238,12 @@ int bmp_display(ulong addr, int x, int y)
 		printf("There is no valid bmp file at the given address\n");
 		return 1;
 	}
+	addr = map_to_sysmem(bmp);
 
 #if defined(CONFIG_LCD)
-	ret = lcd_display_bitmap((ulong)bmp, x, y);
+	ret = lcd_display_bitmap(addr, x, y);
 #elif defined(CONFIG_VIDEO)
-	ret = video_display_bitmap((unsigned long)bmp, x, y);
+	ret = video_display_bitmap(addr, x, y);
 #else
 # error bmp_display() requires CONFIG_LCD or CONFIG_VIDEO
 #endif
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 03/18] dm: core: Call uclass post_bind() after the driver's bind() method
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
  2016-01-05 16:30 ` [U-Boot] [PATCH 01/18] tiny-printf: Always print zeroes Simon Glass
  2016-01-05 16:30 ` [U-Boot] [PATCH 02/18] sandbox: Support the bmp command Simon Glass
@ 2016-01-05 16:30 ` Simon Glass
  2016-01-13 21:55   ` Tom Rini
  2016-01-05 16:31 ` [U-Boot] [PATCH 04/18] bzip2: Support compression for sandbox Simon Glass
                   ` (15 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:30 UTC (permalink / raw)
  To: u-boot

At present the uclass's post_bind() method is called before the driver's
bind() method. This means that the uclass cannot use any of the information
set up by the driver. Move it later in the sequence to permit this.

This is an ordering change which is always fairly major in nature. The main
impact is that devices which have children will not see them appear in their
bind() method. From what I can see, existing drivers do not look at their
children in the bind() method, so this should be safe.

Conceptually this change seems to result in a 'more correct' ordering, since
the uclass (which is broader than the device) gets the last word.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/device.c | 7 +++++++
 drivers/core/uclass.c | 5 -----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index 7a02a93..a9fcac9 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -135,6 +135,11 @@ int device_bind(struct udevice *parent, const struct driver *drv,
 		if (ret)
 			goto fail_child_post_bind;
 	}
+	if (uc->uc_drv->post_bind) {
+		ret = uc->uc_drv->post_bind(dev);
+		if (ret)
+			goto fail_uclass_post_bind;
+	}
 
 	if (parent)
 		dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
@@ -145,6 +150,8 @@ int device_bind(struct udevice *parent, const struct driver *drv,
 
 	return 0;
 
+fail_uclass_post_bind:
+	/* There is no child unbind() method, so no clean-up required */
 fail_child_post_bind:
 	if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
 		if (drv->unbind && drv->unbind(dev)) {
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 1af0947..7f38dae 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -426,11 +426,6 @@ int uclass_bind_device(struct udevice *dev)
 				goto err;
 		}
 	}
-	if (uc->uc_drv->post_bind) {
-		ret = uc->uc_drv->post_bind(dev);
-		if (ret)
-			goto err;
-	}
 
 	return 0;
 err:
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 04/18] bzip2: Support compression for sandbox
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (2 preceding siblings ...)
  2016-01-05 16:30 ` [U-Boot] [PATCH 03/18] dm: core: Call uclass post_bind() after the driver's bind() method Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-13 21:55   ` Tom Rini
  2016-01-05 16:31 ` [U-Boot] [PATCH 05/18] dm: video: Add a video uclass Simon Glass
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

Add the missing code to allow bzip2 compression to be used. This is useful
for sandbox tests. These files are taken from the bzip2 1.0.6 release.
The license text is copied to the top of each file as is done with other
bzip2 files in U-Boot. The only other change is to squash a compiler warning
with nBytes.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 include/bzlib.h             |    3 +
 lib/bzip2/Makefile          |    1 +
 lib/bzip2/bzlib_blocksort.c | 1134 +++++++++++++++++++++++++++++++++++++++++++
 lib/bzip2/bzlib_compress.c  |  714 +++++++++++++++++++++++++++
 4 files changed, 1852 insertions(+)
 create mode 100644 lib/bzip2/bzlib_blocksort.c
 create mode 100644 lib/bzip2/bzlib_compress.c

diff --git a/include/bzlib.h b/include/bzlib.h
index 2d864d5..19314f8 100644
--- a/include/bzlib.h
+++ b/include/bzlib.h
@@ -68,7 +68,10 @@
 
 /* Configure for U-Boot environment */
 #define BZ_NO_STDIO
+
+#ifndef CONFIG_SANDBOX
 #define BZ_NO_COMPRESS
+#endif
 /* End of configuration for U-Boot environment */
 
 #ifdef __cplusplus
diff --git a/lib/bzip2/Makefile b/lib/bzip2/Makefile
index f0b81ad..585d776 100644
--- a/lib/bzip2/Makefile
+++ b/lib/bzip2/Makefile
@@ -4,3 +4,4 @@
 
 obj-y += bzlib.o bzlib_crctable.o bzlib_decompress.o \
 	bzlib_randtable.o bzlib_huffman.o
+obj-$(CONFIG_SANDBOX) += bzlib_compress.o bzlib_blocksort.o
diff --git a/lib/bzip2/bzlib_blocksort.c b/lib/bzip2/bzlib_blocksort.c
new file mode 100644
index 0000000..2785521
--- /dev/null
+++ b/lib/bzip2/bzlib_blocksort.c
@@ -0,0 +1,1134 @@
+
+/*-------------------------------------------------------------*/
+/*--- Block sorting machinery                               ---*/
+/*---                                           blocksort.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2002 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must
+     not claim that you wrote the original software.  If you use this
+     software in a product, an acknowledgment in the product
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote
+     products derived from this software without specific prior written
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward at acm.org
+  bzip2/libbzip2 version 1.0.6 of 6 September 2010
+  Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+#include "bzlib_private.h"
+
+/*---------------------------------------------*/
+/*--- Fallback O(N log(N)^2) sorting        ---*/
+/*--- algorithm, for repetitive blocks      ---*/
+/*---------------------------------------------*/
+
+/*---------------------------------------------*/
+static 
+__inline__
+void fallbackSimpleSort ( UInt32* fmap, 
+                          UInt32* eclass, 
+                          Int32   lo, 
+                          Int32   hi )
+{
+   Int32 i, j, tmp;
+   UInt32 ec_tmp;
+
+   if (lo == hi) return;
+
+   if (hi - lo > 3) {
+      for ( i = hi-4; i >= lo; i-- ) {
+         tmp = fmap[i];
+         ec_tmp = eclass[tmp];
+         for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
+            fmap[j-4] = fmap[j];
+         fmap[j-4] = tmp;
+      }
+   }
+
+   for ( i = hi-1; i >= lo; i-- ) {
+      tmp = fmap[i];
+      ec_tmp = eclass[tmp];
+      for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
+         fmap[j-1] = fmap[j];
+      fmap[j-1] = tmp;
+   }
+}
+
+
+/*---------------------------------------------*/
+#define fswap(zz1, zz2) \
+   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
+
+#define fvswap(zzp1, zzp2, zzn)       \
+{                                     \
+   Int32 yyp1 = (zzp1);               \
+   Int32 yyp2 = (zzp2);               \
+   Int32 yyn  = (zzn);                \
+   while (yyn > 0) {                  \
+      fswap(fmap[yyp1], fmap[yyp2]);  \
+      yyp1++; yyp2++; yyn--;          \
+   }                                  \
+}
+
+
+#define fmin(a,b) ((a) < (b)) ? (a) : (b)
+
+#define fpush(lz,hz) { stackLo[sp] = lz; \
+                       stackHi[sp] = hz; \
+                       sp++; }
+
+#define fpop(lz,hz) { sp--;              \
+                      lz = stackLo[sp];  \
+                      hz = stackHi[sp]; }
+
+#define FALLBACK_QSORT_SMALL_THRESH 10
+#define FALLBACK_QSORT_STACK_SIZE   100
+
+
+static
+void fallbackQSort3 ( UInt32* fmap, 
+                      UInt32* eclass,
+                      Int32   loSt, 
+                      Int32   hiSt )
+{
+   Int32 unLo, unHi, ltLo, gtHi, n, m;
+   Int32 sp, lo, hi;
+   UInt32 med, r, r3;
+   Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
+   Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
+
+   r = 0;
+
+   sp = 0;
+   fpush ( loSt, hiSt );
+
+   while (sp > 0) {
+
+      AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 );
+
+      fpop ( lo, hi );
+      if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
+         fallbackSimpleSort ( fmap, eclass, lo, hi );
+         continue;
+      }
+
+      /* Random partitioning.  Median of 3 sometimes fails to
+         avoid bad cases.  Median of 9 seems to help but 
+         looks rather expensive.  This too seems to work but
+         is cheaper.  Guidance for the magic constants 
+         7621 and 32768 is taken from Sedgewick's algorithms
+         book, chapter 35.
+      */
+      r = ((r * 7621) + 1) % 32768;
+      r3 = r % 3;
+      if (r3 == 0) med = eclass[fmap[lo]]; else
+      if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
+                   med = eclass[fmap[hi]];
+
+      unLo = ltLo = lo;
+      unHi = gtHi = hi;
+
+      while (1) {
+         while (1) {
+            if (unLo > unHi) break;
+            n = (Int32)eclass[fmap[unLo]] - (Int32)med;
+            if (n == 0) { 
+               fswap(fmap[unLo], fmap[ltLo]); 
+               ltLo++; unLo++; 
+               continue; 
+            };
+            if (n > 0) break;
+            unLo++;
+         }
+         while (1) {
+            if (unLo > unHi) break;
+            n = (Int32)eclass[fmap[unHi]] - (Int32)med;
+            if (n == 0) { 
+               fswap(fmap[unHi], fmap[gtHi]); 
+               gtHi--; unHi--; 
+               continue; 
+            };
+            if (n < 0) break;
+            unHi--;
+         }
+         if (unLo > unHi) break;
+         fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
+      }
+
+      AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
+
+      if (gtHi < ltLo) continue;
+
+      n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
+      m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
+
+      n = lo + unLo - ltLo - 1;
+      m = hi - (gtHi - unHi) + 1;
+
+      if (n - lo > hi - m) {
+         fpush ( lo, n );
+         fpush ( m, hi );
+      } else {
+         fpush ( m, hi );
+         fpush ( lo, n );
+      }
+   }
+}
+
+#undef fmin
+#undef fpush
+#undef fpop
+#undef fswap
+#undef fvswap
+#undef FALLBACK_QSORT_SMALL_THRESH
+#undef FALLBACK_QSORT_STACK_SIZE
+
+
+/*---------------------------------------------*/
+/* Pre:
+      nblock > 0
+      eclass exists for [0 .. nblock-1]
+      ((UChar*)eclass) [0 .. nblock-1] holds block
+      ptr exists for [0 .. nblock-1]
+
+   Post:
+      ((UChar*)eclass) [0 .. nblock-1] holds block
+      All other areas of eclass destroyed
+      fmap [0 .. nblock-1] holds sorted order
+      bhtab [ 0 .. 2+(nblock/32) ] destroyed
+*/
+
+#define       SET_BH(zz)  bhtab[(zz) >> 5] |= (1 << ((zz) & 31))
+#define     CLEAR_BH(zz)  bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31))
+#define     ISSET_BH(zz)  (bhtab[(zz) >> 5] & (1 << ((zz) & 31)))
+#define      WORD_BH(zz)  bhtab[(zz) >> 5]
+#define UNALIGNED_BH(zz)  ((zz) & 0x01f)
+
+static
+void fallbackSort ( UInt32* fmap, 
+                    UInt32* eclass, 
+                    UInt32* bhtab,
+                    Int32   nblock,
+                    Int32   verb )
+{
+   Int32 ftab[257];
+   Int32 ftabCopy[256];
+   Int32 H, i, j, k, l, r, cc, cc1;
+   Int32 nNotDone;
+   Int32 nBhtab;
+   UChar* eclass8 = (UChar*)eclass;
+
+   /*--
+      Initial 1-char radix sort to generate
+      initial fmap and initial BH bits.
+   --*/
+   if (verb >= 4)
+      VPrintf0 ( "        bucket sorting ...\n" );
+   for (i = 0; i < 257;    i++) ftab[i] = 0;
+   for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
+   for (i = 0; i < 256;    i++) ftabCopy[i] = ftab[i];
+   for (i = 1; i < 257;    i++) ftab[i] += ftab[i-1];
+
+   for (i = 0; i < nblock; i++) {
+      j = eclass8[i];
+      k = ftab[j] - 1;
+      ftab[j] = k;
+      fmap[k] = i;
+   }
+
+   nBhtab = 2 + (nblock / 32);
+   for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
+   for (i = 0; i < 256; i++) SET_BH(ftab[i]);
+
+   /*--
+      Inductively refine the buckets.  Kind-of an
+      "exponential radix sort" (!), inspired by the
+      Manber-Myers suffix array construction algorithm.
+   --*/
+
+   /*-- set sentinel bits for block-end detection --*/
+   for (i = 0; i < 32; i++) { 
+      SET_BH(nblock + 2*i);
+      CLEAR_BH(nblock + 2*i + 1);
+   }
+
+   /*-- the log(N) loop --*/
+   H = 1;
+   while (1) {
+
+      if (verb >= 4) 
+         VPrintf1 ( "        depth %6d has ", H );
+
+      j = 0;
+      for (i = 0; i < nblock; i++) {
+         if (ISSET_BH(i)) j = i;
+         k = fmap[i] - H; if (k < 0) k += nblock;
+         eclass[k] = j;
+      }
+
+      nNotDone = 0;
+      r = -1;
+      while (1) {
+
+	 /*-- find the next non-singleton bucket --*/
+         k = r + 1;
+         while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
+         if (ISSET_BH(k)) {
+            while (WORD_BH(k) == 0xffffffff) k += 32;
+            while (ISSET_BH(k)) k++;
+         }
+         l = k - 1;
+         if (l >= nblock) break;
+         while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
+         if (!ISSET_BH(k)) {
+            while (WORD_BH(k) == 0x00000000) k += 32;
+            while (!ISSET_BH(k)) k++;
+         }
+         r = k - 1;
+         if (r >= nblock) break;
+
+         /*-- now [l, r] bracket current bucket --*/
+         if (r > l) {
+            nNotDone += (r - l + 1);
+            fallbackQSort3 ( fmap, eclass, l, r );
+
+            /*-- scan bucket and generate header bits-- */
+            cc = -1;
+            for (i = l; i <= r; i++) {
+               cc1 = eclass[fmap[i]];
+               if (cc != cc1) { SET_BH(i); cc = cc1; };
+            }
+         }
+      }
+
+      if (verb >= 4) 
+         VPrintf1 ( "%6d unresolved strings\n", nNotDone );
+
+      H *= 2;
+      if (H > nblock || nNotDone == 0) break;
+   }
+
+   /*-- 
+      Reconstruct the original block in
+      eclass8 [0 .. nblock-1], since the
+      previous phase destroyed it.
+   --*/
+   if (verb >= 4)
+      VPrintf0 ( "        reconstructing block ...\n" );
+   j = 0;
+   for (i = 0; i < nblock; i++) {
+      while (ftabCopy[j] == 0) j++;
+      ftabCopy[j]--;
+      eclass8[fmap[i]] = (UChar)j;
+   }
+   AssertH ( j < 256, 1005 );
+}
+
+#undef       SET_BH
+#undef     CLEAR_BH
+#undef     ISSET_BH
+#undef      WORD_BH
+#undef UNALIGNED_BH
+
+
+/*---------------------------------------------*/
+/*--- The main, O(N^2 log(N)) sorting       ---*/
+/*--- algorithm.  Faster for "normal"       ---*/
+/*--- non-repetitive blocks.                ---*/
+/*---------------------------------------------*/
+
+/*---------------------------------------------*/
+static
+__inline__
+Bool mainGtU ( UInt32  i1, 
+               UInt32  i2,
+               UChar*  block, 
+               UInt16* quadrant,
+               UInt32  nblock,
+               Int32*  budget )
+{
+   Int32  k;
+   UChar  c1, c2;
+   UInt16 s1, s2;
+
+   AssertD ( i1 != i2, "mainGtU" );
+   /* 1 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 2 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 3 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 4 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 5 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 6 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 7 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 8 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 9 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 10 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 11 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 12 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+
+   k = nblock + 8;
+
+   do {
+      /* 1 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 2 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 3 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 4 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 5 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 6 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 7 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 8 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+
+      if (i1 >= nblock) i1 -= nblock;
+      if (i2 >= nblock) i2 -= nblock;
+
+      k -= 8;
+      (*budget)--;
+   }
+      while (k >= 0);
+
+   return False;
+}
+
+
+/*---------------------------------------------*/
+/*--
+   Knuth's increments seem to work better
+   than Incerpi-Sedgewick here.  Possibly
+   because the number of elems to sort is
+   usually small, typically <= 20.
+--*/
+static
+Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
+                   9841, 29524, 88573, 265720,
+                   797161, 2391484 };
+
+static
+void mainSimpleSort ( UInt32* ptr,
+                      UChar*  block,
+                      UInt16* quadrant,
+                      Int32   nblock,
+                      Int32   lo, 
+                      Int32   hi, 
+                      Int32   d,
+                      Int32*  budget )
+{
+   Int32 i, j, h, bigN, hp;
+   UInt32 v;
+
+   bigN = hi - lo + 1;
+   if (bigN < 2) return;
+
+   hp = 0;
+   while (incs[hp] < bigN) hp++;
+   hp--;
+
+   for (; hp >= 0; hp--) {
+      h = incs[hp];
+
+      i = lo + h;
+      while (True) {
+
+         /*-- copy 1 --*/
+         if (i > hi) break;
+         v = ptr[i];
+         j = i;
+         while ( mainGtU ( 
+                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
+                 ) ) {
+            ptr[j] = ptr[j-h];
+            j = j - h;
+            if (j <= (lo + h - 1)) break;
+         }
+         ptr[j] = v;
+         i++;
+
+         /*-- copy 2 --*/
+         if (i > hi) break;
+         v = ptr[i];
+         j = i;
+         while ( mainGtU ( 
+                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
+                 ) ) {
+            ptr[j] = ptr[j-h];
+            j = j - h;
+            if (j <= (lo + h - 1)) break;
+         }
+         ptr[j] = v;
+         i++;
+
+         /*-- copy 3 --*/
+         if (i > hi) break;
+         v = ptr[i];
+         j = i;
+         while ( mainGtU ( 
+                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
+                 ) ) {
+            ptr[j] = ptr[j-h];
+            j = j - h;
+            if (j <= (lo + h - 1)) break;
+         }
+         ptr[j] = v;
+         i++;
+
+         if (*budget < 0) return;
+      }
+   }
+}
+
+
+/*---------------------------------------------*/
+/*--
+   The following is an implementation of
+   an elegant 3-way quicksort for strings,
+   described in a paper "Fast Algorithms for
+   Sorting and Searching Strings", by Robert
+   Sedgewick and Jon L. Bentley.
+--*/
+
+#define mswap(zz1, zz2) \
+   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
+
+#define mvswap(zzp1, zzp2, zzn)       \
+{                                     \
+   Int32 yyp1 = (zzp1);               \
+   Int32 yyp2 = (zzp2);               \
+   Int32 yyn  = (zzn);                \
+   while (yyn > 0) {                  \
+      mswap(ptr[yyp1], ptr[yyp2]);    \
+      yyp1++; yyp2++; yyn--;          \
+   }                                  \
+}
+
+static 
+__inline__
+UChar mmed3 ( UChar a, UChar b, UChar c )
+{
+   UChar t;
+   if (a > b) { t = a; a = b; b = t; };
+   if (b > c) { 
+      b = c;
+      if (a > b) b = a;
+   }
+   return b;
+}
+
+#define mmin(a,b) ((a) < (b)) ? (a) : (b)
+
+#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
+                          stackHi[sp] = hz; \
+                          stackD [sp] = dz; \
+                          sp++; }
+
+#define mpop(lz,hz,dz) { sp--;             \
+                         lz = stackLo[sp]; \
+                         hz = stackHi[sp]; \
+                         dz = stackD [sp]; }
+
+
+#define mnextsize(az) (nextHi[az]-nextLo[az])
+
+#define mnextswap(az,bz)                                        \
+   { Int32 tz;                                                  \
+     tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
+     tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
+     tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
+
+
+#define MAIN_QSORT_SMALL_THRESH 20
+#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT)
+#define MAIN_QSORT_STACK_SIZE 100
+
+static
+void mainQSort3 ( UInt32* ptr,
+                  UChar*  block,
+                  UInt16* quadrant,
+                  Int32   nblock,
+                  Int32   loSt, 
+                  Int32   hiSt, 
+                  Int32   dSt,
+                  Int32*  budget )
+{
+   Int32 unLo, unHi, ltLo, gtHi, n, m, med;
+   Int32 sp, lo, hi, d;
+
+   Int32 stackLo[MAIN_QSORT_STACK_SIZE];
+   Int32 stackHi[MAIN_QSORT_STACK_SIZE];
+   Int32 stackD [MAIN_QSORT_STACK_SIZE];
+
+   Int32 nextLo[3];
+   Int32 nextHi[3];
+   Int32 nextD [3];
+
+   sp = 0;
+   mpush ( loSt, hiSt, dSt );
+
+   while (sp > 0) {
+
+      AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 );
+
+      mpop ( lo, hi, d );
+      if (hi - lo < MAIN_QSORT_SMALL_THRESH || 
+          d > MAIN_QSORT_DEPTH_THRESH) {
+         mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
+         if (*budget < 0) return;
+         continue;
+      }
+
+      med = (Int32) 
+            mmed3 ( block[ptr[ lo         ]+d],
+                    block[ptr[ hi         ]+d],
+                    block[ptr[ (lo+hi)>>1 ]+d] );
+
+      unLo = ltLo = lo;
+      unHi = gtHi = hi;
+
+      while (True) {
+         while (True) {
+            if (unLo > unHi) break;
+            n = ((Int32)block[ptr[unLo]+d]) - med;
+            if (n == 0) { 
+               mswap(ptr[unLo], ptr[ltLo]); 
+               ltLo++; unLo++; continue; 
+            };
+            if (n >  0) break;
+            unLo++;
+         }
+         while (True) {
+            if (unLo > unHi) break;
+            n = ((Int32)block[ptr[unHi]+d]) - med;
+            if (n == 0) { 
+               mswap(ptr[unHi], ptr[gtHi]); 
+               gtHi--; unHi--; continue; 
+            };
+            if (n <  0) break;
+            unHi--;
+         }
+         if (unLo > unHi) break;
+         mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
+      }
+
+      AssertD ( unHi == unLo-1, "mainQSort3(2)" );
+
+      if (gtHi < ltLo) {
+         mpush(lo, hi, d+1 );
+         continue;
+      }
+
+      n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
+      m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
+
+      n = lo + unLo - ltLo - 1;
+      m = hi - (gtHi - unHi) + 1;
+
+      nextLo[0] = lo;  nextHi[0] = n;   nextD[0] = d;
+      nextLo[1] = m;   nextHi[1] = hi;  nextD[1] = d;
+      nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
+
+      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
+      if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
+      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
+
+      AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
+      AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
+
+      mpush (nextLo[0], nextHi[0], nextD[0]);
+      mpush (nextLo[1], nextHi[1], nextD[1]);
+      mpush (nextLo[2], nextHi[2], nextD[2]);
+   }
+}
+
+#undef mswap
+#undef mvswap
+#undef mpush
+#undef mpop
+#undef mmin
+#undef mnextsize
+#undef mnextswap
+#undef MAIN_QSORT_SMALL_THRESH
+#undef MAIN_QSORT_DEPTH_THRESH
+#undef MAIN_QSORT_STACK_SIZE
+
+
+/*---------------------------------------------*/
+/* Pre:
+      nblock > N_OVERSHOOT
+      block32 exists for [0 .. nblock-1 +N_OVERSHOOT]
+      ((UChar*)block32) [0 .. nblock-1] holds block
+      ptr exists for [0 .. nblock-1]
+
+   Post:
+      ((UChar*)block32) [0 .. nblock-1] holds block
+      All other areas of block32 destroyed
+      ftab [0 .. 65536 ] destroyed
+      ptr [0 .. nblock-1] holds sorted order
+      if (*budget < 0), sorting was abandoned
+*/
+
+#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
+#define SETMASK (1 << 21)
+#define CLEARMASK (~(SETMASK))
+
+static
+void mainSort ( UInt32* ptr, 
+                UChar*  block,
+                UInt16* quadrant, 
+                UInt32* ftab,
+                Int32   nblock,
+                Int32   verb,
+                Int32*  budget )
+{
+   Int32  i, j, k, ss, sb;
+   Int32  runningOrder[256];
+   Bool   bigDone[256];
+   Int32  copyStart[256];
+   Int32  copyEnd  [256];
+   UChar  c1;
+   Int32  numQSorted;
+   UInt16 s;
+   if (verb >= 4) VPrintf0 ( "        main sort initialise ...\n" );
+
+   /*-- set up the 2-byte frequency table --*/
+   for (i = 65536; i >= 0; i--) ftab[i] = 0;
+
+   j = block[0] << 8;
+   i = nblock-1;
+   for (; i >= 3; i -= 4) {
+      quadrant[i] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
+      ftab[j]++;
+      quadrant[i-1] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
+      ftab[j]++;
+      quadrant[i-2] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
+      ftab[j]++;
+      quadrant[i-3] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
+      ftab[j]++;
+   }
+   for (; i >= 0; i--) {
+      quadrant[i] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
+      ftab[j]++;
+   }
+
+   /*-- (emphasises close relationship of block & quadrant) --*/
+   for (i = 0; i < BZ_N_OVERSHOOT; i++) {
+      block   [nblock+i] = block[i];
+      quadrant[nblock+i] = 0;
+   }
+
+   if (verb >= 4) VPrintf0 ( "        bucket sorting ...\n" );
+
+   /*-- Complete the initial radix sort --*/
+   for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
+
+   s = block[0] << 8;
+   i = nblock-1;
+   for (; i >= 3; i -= 4) {
+      s = (s >> 8) | (block[i] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i;
+      s = (s >> 8) | (block[i-1] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i-1;
+      s = (s >> 8) | (block[i-2] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i-2;
+      s = (s >> 8) | (block[i-3] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i-3;
+   }
+   for (; i >= 0; i--) {
+      s = (s >> 8) | (block[i] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i;
+   }
+
+   /*--
+      Now ftab contains the first loc of every small bucket.
+      Calculate the running order, from smallest to largest
+      big bucket.
+   --*/
+   for (i = 0; i <= 255; i++) {
+      bigDone     [i] = False;
+      runningOrder[i] = i;
+   }
+
+   {
+      Int32 vv;
+      Int32 h = 1;
+      do h = 3 * h + 1; while (h <= 256);
+      do {
+         h = h / 3;
+         for (i = h; i <= 255; i++) {
+            vv = runningOrder[i];
+            j = i;
+            while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
+               runningOrder[j] = runningOrder[j-h];
+               j = j - h;
+               if (j <= (h - 1)) goto zero;
+            }
+            zero:
+            runningOrder[j] = vv;
+         }
+      } while (h != 1);
+   }
+
+   /*--
+      The main sorting loop.
+   --*/
+
+   numQSorted = 0;
+
+   for (i = 0; i <= 255; i++) {
+
+      /*--
+         Process big buckets, starting with the least full.
+         Basically this is a 3-step process in which we call
+         mainQSort3 to sort the small buckets [ss, j], but
+         also make a big effort to avoid the calls if we can.
+      --*/
+      ss = runningOrder[i];
+
+      /*--
+         Step 1:
+         Complete the big bucket [ss] by quicksorting
+         any unsorted small buckets [ss, j], for j != ss.  
+         Hopefully previous pointer-scanning phases have already
+         completed many of the small buckets [ss, j], so
+         we don't have to sort them@all.
+      --*/
+      for (j = 0; j <= 255; j++) {
+         if (j != ss) {
+            sb = (ss << 8) + j;
+            if ( ! (ftab[sb] & SETMASK) ) {
+               Int32 lo = ftab[sb]   & CLEARMASK;
+               Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
+               if (hi > lo) {
+                  if (verb >= 4)
+                     VPrintf4 ( "        qsort [0x%x, 0x%x]   "
+                                "done %d   this %d\n",
+                                ss, j, numQSorted, hi - lo + 1 );
+                  mainQSort3 ( 
+                     ptr, block, quadrant, nblock, 
+                     lo, hi, BZ_N_RADIX, budget 
+                  );   
+                  numQSorted += (hi - lo + 1);
+                  if (*budget < 0) return;
+               }
+            }
+            ftab[sb] |= SETMASK;
+         }
+      }
+
+      AssertH ( !bigDone[ss], 1006 );
+
+      /*--
+         Step 2:
+         Now scan this big bucket [ss] so as to synthesise the
+         sorted order for small buckets [t, ss] for all t,
+         including, magically, the bucket [ss,ss] too.
+         This will avoid doing Real Work in subsequent Step 1's.
+      --*/
+      {
+         for (j = 0; j <= 255; j++) {
+            copyStart[j] =  ftab[(j << 8) + ss]     & CLEARMASK;
+            copyEnd  [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
+         }
+         for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
+            k = ptr[j]-1; if (k < 0) k += nblock;
+            c1 = block[k];
+            if (!bigDone[c1])
+               ptr[ copyStart[c1]++ ] = k;
+         }
+         for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
+            k = ptr[j]-1; if (k < 0) k += nblock;
+            c1 = block[k];
+            if (!bigDone[c1]) 
+               ptr[ copyEnd[c1]-- ] = k;
+         }
+      }
+
+      AssertH ( (copyStart[ss]-1 == copyEnd[ss])
+                || 
+                /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1.
+                   Necessity for this case is demonstrated by compressing 
+                   a sequence of approximately 48.5 million of character 
+                   251; 1.0.0/1.0.1 will then die here. */
+                (copyStart[ss] == 0 && copyEnd[ss] == nblock-1),
+                1007 )
+
+      for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK;
+
+      /*--
+         Step 3:
+         The [ss] big bucket is now done.  Record this fact,
+         and update the quadrant descriptors.  Remember to
+         update quadrants in the overshoot area too, if
+         necessary.  The "if (i < 255)" test merely skips
+         this updating for the last bucket processed, since
+         updating for the last bucket is pointless.
+
+         The quadrant array provides a way to incrementally
+         cache sort orderings, as they appear, so as to 
+         make subsequent comparisons in fullGtU() complete
+         faster.  For repetitive blocks this makes a big
+         difference (but not big enough to be able to avoid
+         the fallback sorting mechanism, exponential radix sort).
+
+         The precise meaning is: at all times:
+
+            for 0 <= i < nblock and 0 <= j <= nblock
+
+            if block[i] != block[j], 
+
+               then the relative values of quadrant[i] and 
+                    quadrant[j] are meaningless.
+
+               else {
+                  if quadrant[i] < quadrant[j]
+                     then the string starting at i lexicographically
+                     precedes the string starting@j
+
+                  else if quadrant[i] > quadrant[j]
+                     then the string starting at j lexicographically
+                     precedes the string starting at i
+
+                  else
+                     the relative ordering of the strings starting
+                     at i and j has not yet been determined.
+               }
+      --*/
+      bigDone[ss] = True;
+
+      if (i < 255) {
+         Int32 bbStart  = ftab[ss << 8] & CLEARMASK;
+         Int32 bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
+         Int32 shifts   = 0;
+
+         while ((bbSize >> shifts) > 65534) shifts++;
+
+         for (j = bbSize-1; j >= 0; j--) {
+            Int32 a2update     = ptr[bbStart + j];
+            UInt16 qVal        = (UInt16)(j >> shifts);
+            quadrant[a2update] = qVal;
+            if (a2update < BZ_N_OVERSHOOT)
+               quadrant[a2update + nblock] = qVal;
+         }
+         AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
+      }
+
+   }
+
+   if (verb >= 4)
+      VPrintf3 ( "        %d pointers, %d sorted, %d scanned\n",
+                 nblock, numQSorted, nblock - numQSorted );
+}
+
+#undef BIGFREQ
+#undef SETMASK
+#undef CLEARMASK
+
+
+/*---------------------------------------------*/
+/* Pre:
+      nblock > 0
+      arr2 exists for [0 .. nblock-1 +N_OVERSHOOT]
+      ((UChar*)arr2)  [0 .. nblock-1] holds block
+      arr1 exists for [0 .. nblock-1]
+
+   Post:
+      ((UChar*)arr2) [0 .. nblock-1] holds block
+      All other areas of block destroyed
+      ftab [ 0 .. 65536 ] destroyed
+      arr1 [0 .. nblock-1] holds sorted order
+*/
+void BZ2_blockSort ( EState* s )
+{
+   UInt32* ptr    = s->ptr; 
+   UChar*  block  = s->block;
+   UInt32* ftab   = s->ftab;
+   Int32   nblock = s->nblock;
+   Int32   verb   = s->verbosity;
+   Int32   wfact  = s->workFactor;
+   UInt16* quadrant;
+   Int32   budget;
+   Int32   budgetInit;
+   Int32   i;
+
+   if (nblock < 10000) {
+      fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
+   } else {
+      /* Calculate the location for quadrant, remembering to get
+         the alignment right.  Assumes that &(block[0]) is at least
+         2-byte aligned -- this should be ok since block is really
+         the first section of arr2.
+      */
+      i = nblock+BZ_N_OVERSHOOT;
+      if (i & 1) i++;
+      quadrant = (UInt16*)(&(block[i]));
+
+      /* (wfact-1) / 3 puts the default-factor-30
+         transition point at very roughly the same place as 
+         with v0.1 and v0.9.0.  
+         Not that it particularly matters any more, since the
+         resulting compressed stream is now the same regardless
+         of whether or not we use the main sort or fallback sort.
+      */
+      if (wfact < 1  ) wfact = 1;
+      if (wfact > 100) wfact = 100;
+      budgetInit = nblock * ((wfact-1) / 3);
+      budget = budgetInit;
+
+      mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
+      if (verb >= 3) 
+         VPrintf3 ( "      %d work, %d block, ratio %5.2f\n",
+                    budgetInit - budget,
+                    nblock, 
+                    (float)(budgetInit - budget) /
+                    (float)(nblock==0 ? 1 : nblock) ); 
+      if (budget < 0) {
+         if (verb >= 2) 
+            VPrintf0 ( "    too repetitive; using fallback"
+                       " sorting algorithm\n" );
+         fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
+      }
+   }
+
+   s->origPtr = -1;
+   for (i = 0; i < s->nblock; i++)
+      if (ptr[i] == 0)
+         { s->origPtr = i; break; };
+
+   AssertH( s->origPtr != -1, 1003 );
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                       blocksort.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/lib/bzip2/bzlib_compress.c b/lib/bzip2/bzlib_compress.c
new file mode 100644
index 0000000..c8da1c7
--- /dev/null
+++ b/lib/bzip2/bzlib_compress.c
@@ -0,0 +1,714 @@
+
+/*-------------------------------------------------------------*/
+/*--- Compression machinery (not incl block sorting)        ---*/
+/*---                                            compress.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2002 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must
+     not claim that you wrote the original software.  If you use this
+     software in a product, an acknowledgment in the product
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote
+     products derived from this software without specific prior written
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward at acm.org
+  bzip2/libbzip2 version 1.0.6 of 6 September 2010
+  Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+/* CHANGES
+    0.9.0    -- original version.
+    0.9.0a/b -- no changes in this file.
+    0.9.0c   -- changed setting of nGroups in sendMTFValues() 
+                so as to do a bit better on small files
+*/
+
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------------*/
+/*--- Bit stream I/O                              ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+void BZ2_bsInitWrite ( EState* s )
+{
+   s->bsLive = 0;
+   s->bsBuff = 0;
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsFinishWrite ( EState* s )
+{
+   while (s->bsLive > 0) {
+      s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
+      s->numZ++;
+      s->bsBuff <<= 8;
+      s->bsLive -= 8;
+   }
+}
+
+
+/*---------------------------------------------------*/
+#define bsNEEDW(nz)                           \
+{                                             \
+   while (s->bsLive >= 8) {                   \
+      s->zbits[s->numZ]                       \
+         = (UChar)(s->bsBuff >> 24);          \
+      s->numZ++;                              \
+      s->bsBuff <<= 8;                        \
+      s->bsLive -= 8;                         \
+   }                                          \
+}
+
+
+/*---------------------------------------------------*/
+static
+__inline__
+void bsW ( EState* s, Int32 n, UInt32 v )
+{
+   bsNEEDW ( n );
+   s->bsBuff |= (v << (32 - s->bsLive - n));
+   s->bsLive += n;
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsPutUInt32 ( EState* s, UInt32 u )
+{
+   bsW ( s, 8, (u >> 24) & 0xffL );
+   bsW ( s, 8, (u >> 16) & 0xffL );
+   bsW ( s, 8, (u >>  8) & 0xffL );
+   bsW ( s, 8,  u        & 0xffL );
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsPutUChar ( EState* s, UChar c )
+{
+   bsW( s, 8, (UInt32)c );
+}
+
+
+/*---------------------------------------------------*/
+/*--- The back end proper                         ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+static
+void makeMaps_e ( EState* s )
+{
+   Int32 i;
+   s->nInUse = 0;
+   for (i = 0; i < 256; i++)
+      if (s->inUse[i]) {
+         s->unseqToSeq[i] = s->nInUse;
+         s->nInUse++;
+      }
+}
+
+
+/*---------------------------------------------------*/
+static
+void generateMTFValues ( EState* s )
+{
+   UChar   yy[256];
+   Int32   i, j;
+   Int32   zPend;
+   Int32   wr;
+   Int32   EOB;
+
+   /* 
+      After sorting (eg, here),
+         s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
+         and
+         ((UChar*)s->arr2) [ 0 .. s->nblock-1 ] 
+         holds the original block data.
+
+      The first thing to do is generate the MTF values,
+      and put them in
+         ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
+      Because there are strictly fewer or equal MTF values
+      than block values, ptr values in this area are overwritten
+      with MTF values only when they are no longer needed.
+
+      The final compressed bitstream is generated into the
+      area starting at
+         (UChar*) (&((UChar*)s->arr2)[s->nblock])
+
+      These storage aliases are set up in bzCompressInit(),
+      except for the last one, which is arranged in 
+      compressBlock().
+   */
+   UInt32* ptr   = s->ptr;
+   UChar* block  = s->block;
+   UInt16* mtfv  = s->mtfv;
+
+   makeMaps_e ( s );
+   EOB = s->nInUse+1;
+
+   for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
+
+   wr = 0;
+   zPend = 0;
+   for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
+
+   for (i = 0; i < s->nblock; i++) {
+      UChar ll_i;
+      AssertD ( wr <= i, "generateMTFValues(1)" );
+      j = ptr[i]-1; if (j < 0) j += s->nblock;
+      ll_i = s->unseqToSeq[block[j]];
+      AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
+
+      if (yy[0] == ll_i) { 
+         zPend++;
+      } else {
+
+         if (zPend > 0) {
+            zPend--;
+            while (True) {
+               if (zPend & 1) {
+                  mtfv[wr] = BZ_RUNB; wr++; 
+                  s->mtfFreq[BZ_RUNB]++; 
+               } else {
+                  mtfv[wr] = BZ_RUNA; wr++; 
+                  s->mtfFreq[BZ_RUNA]++; 
+               }
+               if (zPend < 2) break;
+               zPend = (zPend - 2) / 2;
+            };
+            zPend = 0;
+         }
+         {
+            register UChar  rtmp;
+            register UChar* ryy_j;
+            register UChar  rll_i;
+            rtmp  = yy[1];
+            yy[1] = yy[0];
+            ryy_j = &(yy[1]);
+            rll_i = ll_i;
+            while ( rll_i != rtmp ) {
+               register UChar rtmp2;
+               ryy_j++;
+               rtmp2  = rtmp;
+               rtmp   = *ryy_j;
+               *ryy_j = rtmp2;
+            };
+            yy[0] = rtmp;
+            j = ryy_j - &(yy[0]);
+            mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
+         }
+
+      }
+   }
+
+   if (zPend > 0) {
+      zPend--;
+      while (True) {
+         if (zPend & 1) {
+            mtfv[wr] = BZ_RUNB; wr++; 
+            s->mtfFreq[BZ_RUNB]++; 
+         } else {
+            mtfv[wr] = BZ_RUNA; wr++; 
+            s->mtfFreq[BZ_RUNA]++; 
+         }
+         if (zPend < 2) break;
+         zPend = (zPend - 2) / 2;
+      };
+      zPend = 0;
+   }
+
+   mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
+
+   s->nMTF = wr;
+}
+
+
+/*---------------------------------------------------*/
+#define BZ_LESSER_ICOST  0
+#define BZ_GREATER_ICOST 15
+
+static
+void sendMTFValues ( EState* s )
+{
+   Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
+   Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
+   Int32 nGroups, nBytes;
+
+   /*--
+   UChar  len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+   is a global since the decoder also needs it.
+
+   Int32  code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+   Int32  rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+   are also globals only used in this proc.
+   Made global to keep stack frame size small.
+   --*/
+
+
+   UInt16 cost[BZ_N_GROUPS];
+   Int32  fave[BZ_N_GROUPS];
+
+   UInt16* mtfv = s->mtfv;
+
+   if (s->verbosity >= 3)
+      VPrintf3( "      %d in block, %d after MTF & 1-2 coding, "
+                "%d+2 syms in use\n", 
+                s->nblock, s->nMTF, s->nInUse );
+
+   alphaSize = s->nInUse+2;
+   for (t = 0; t < BZ_N_GROUPS; t++)
+      for (v = 0; v < alphaSize; v++)
+         s->len[t][v] = BZ_GREATER_ICOST;
+
+   /*--- Decide how many coding tables to use ---*/
+   AssertH ( s->nMTF > 0, 3001 );
+   if (s->nMTF < 200)  nGroups = 2; else
+   if (s->nMTF < 600)  nGroups = 3; else
+   if (s->nMTF < 1200) nGroups = 4; else
+   if (s->nMTF < 2400) nGroups = 5; else
+                       nGroups = 6;
+
+   /*--- Generate an initial set of coding tables ---*/
+   { 
+      Int32 nPart, remF, tFreq, aFreq;
+
+      nPart = nGroups;
+      remF  = s->nMTF;
+      gs = 0;
+      while (nPart > 0) {
+         tFreq = remF / nPart;
+         ge = gs-1;
+         aFreq = 0;
+         while (aFreq < tFreq && ge < alphaSize-1) {
+            ge++;
+            aFreq += s->mtfFreq[ge];
+         }
+
+         if (ge > gs 
+             && nPart != nGroups && nPart != 1 
+             && ((nGroups-nPart) % 2 == 1)) {
+            aFreq -= s->mtfFreq[ge];
+            ge--;
+         }
+
+         if (s->verbosity >= 3)
+            VPrintf5( "      initial group %d, [%d .. %d], "
+                      "has %d syms (%4.1f%%)\n",
+                      nPart, gs, ge, aFreq, 
+                      (100.0 * (float)aFreq) / (float)(s->nMTF) );
+ 
+         for (v = 0; v < alphaSize; v++)
+            if (v >= gs && v <= ge) 
+               s->len[nPart-1][v] = BZ_LESSER_ICOST; else
+               s->len[nPart-1][v] = BZ_GREATER_ICOST;
+ 
+         nPart--;
+         gs = ge+1;
+         remF -= aFreq;
+      }
+   }
+
+   /*--- 
+      Iterate up to BZ_N_ITERS times to improve the tables.
+   ---*/
+   for (iter = 0; iter < BZ_N_ITERS; iter++) {
+
+      for (t = 0; t < nGroups; t++) fave[t] = 0;
+
+      for (t = 0; t < nGroups; t++)
+         for (v = 0; v < alphaSize; v++)
+            s->rfreq[t][v] = 0;
+
+      /*---
+        Set up an auxiliary length table which is used to fast-track
+	the common case (nGroups == 6). 
+      ---*/
+      if (nGroups == 6) {
+         for (v = 0; v < alphaSize; v++) {
+            s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
+            s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
+            s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
+	 }
+      }
+
+      nSelectors = 0;
+      totc = 0;
+      gs = 0;
+      while (True) {
+
+         /*--- Set group start & end marks. --*/
+         if (gs >= s->nMTF) break;
+         ge = gs + BZ_G_SIZE - 1; 
+         if (ge >= s->nMTF) ge = s->nMTF-1;
+
+         /*-- 
+            Calculate the cost of this group as coded
+            by each of the coding tables.
+         --*/
+         for (t = 0; t < nGroups; t++) cost[t] = 0;
+
+         if (nGroups == 6 && 50 == ge-gs+1) {
+            /*--- fast track the common case ---*/
+            register UInt32 cost01, cost23, cost45;
+            register UInt16 icv;
+            cost01 = cost23 = cost45 = 0;
+
+#           define BZ_ITER(nn)                \
+               icv = mtfv[gs+(nn)];           \
+               cost01 += s->len_pack[icv][0]; \
+               cost23 += s->len_pack[icv][1]; \
+               cost45 += s->len_pack[icv][2]; \
+
+            BZ_ITER(0);  BZ_ITER(1);  BZ_ITER(2);  BZ_ITER(3);  BZ_ITER(4);
+            BZ_ITER(5);  BZ_ITER(6);  BZ_ITER(7);  BZ_ITER(8);  BZ_ITER(9);
+            BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
+            BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
+            BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
+            BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
+            BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
+            BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
+            BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
+            BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
+
+#           undef BZ_ITER
+
+            cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
+            cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
+            cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
+
+         } else {
+	    /*--- slow version which correctly handles all situations ---*/
+            for (i = gs; i <= ge; i++) { 
+               UInt16 icv = mtfv[i];
+               for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
+            }
+         }
+ 
+         /*-- 
+            Find the coding table which is best for this group,
+            and record its identity in the selector table.
+         --*/
+         bc = 999999999; bt = -1;
+         for (t = 0; t < nGroups; t++)
+            if (cost[t] < bc) { bc = cost[t]; bt = t; };
+         totc += bc;
+         fave[bt]++;
+         s->selector[nSelectors] = bt;
+         nSelectors++;
+
+         /*-- 
+            Increment the symbol frequencies for the selected table.
+          --*/
+         if (nGroups == 6 && 50 == ge-gs+1) {
+            /*--- fast track the common case ---*/
+
+#           define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
+
+            BZ_ITUR(0);  BZ_ITUR(1);  BZ_ITUR(2);  BZ_ITUR(3);  BZ_ITUR(4);
+            BZ_ITUR(5);  BZ_ITUR(6);  BZ_ITUR(7);  BZ_ITUR(8);  BZ_ITUR(9);
+            BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
+            BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
+            BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
+            BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
+            BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
+            BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
+            BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
+            BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
+
+#           undef BZ_ITUR
+
+         } else {
+	    /*--- slow version which correctly handles all situations ---*/
+            for (i = gs; i <= ge; i++)
+               s->rfreq[bt][ mtfv[i] ]++;
+         }
+
+         gs = ge+1;
+      }
+      if (s->verbosity >= 3) {
+         VPrintf2 ( "      pass %d: size is %d, grp uses are ", 
+                   iter+1, totc/8 );
+         for (t = 0; t < nGroups; t++)
+            VPrintf1 ( "%d ", fave[t] );
+         VPrintf0 ( "\n" );
+      }
+
+      /*--
+        Recompute the tables based on the accumulated frequencies.
+      --*/
+      /* maxLen was changed from 20 to 17 in bzip2-1.0.3.  See 
+         comment in huffman.c for details. */
+      for (t = 0; t < nGroups; t++)
+         BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]), 
+                                 alphaSize, 17 /*20*/ );
+   }
+
+
+   AssertH( nGroups < 8, 3002 );
+   AssertH( nSelectors < 32768 &&
+            nSelectors <= (2 + (900000 / BZ_G_SIZE)),
+            3003 );
+
+
+   /*--- Compute MTF values for the selectors. ---*/
+   {
+      UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
+      for (i = 0; i < nGroups; i++) pos[i] = i;
+      for (i = 0; i < nSelectors; i++) {
+         ll_i = s->selector[i];
+         j = 0;
+         tmp = pos[j];
+         while ( ll_i != tmp ) {
+            j++;
+            tmp2 = tmp;
+            tmp = pos[j];
+            pos[j] = tmp2;
+         };
+         pos[0] = tmp;
+         s->selectorMtf[i] = j;
+      }
+   };
+
+   /*--- Assign actual codes for the tables. --*/
+   for (t = 0; t < nGroups; t++) {
+      minLen = 32;
+      maxLen = 0;
+      for (i = 0; i < alphaSize; i++) {
+         if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
+         if (s->len[t][i] < minLen) minLen = s->len[t][i];
+      }
+      AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
+      AssertH ( !(minLen < 1),  3005 );
+      BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]), 
+                          minLen, maxLen, alphaSize );
+   }
+
+   /*--- Transmit the mapping table. ---*/
+   { 
+      Bool inUse16[16];
+      for (i = 0; i < 16; i++) {
+          inUse16[i] = False;
+          for (j = 0; j < 16; j++)
+             if (s->inUse[i * 16 + j]) inUse16[i] = True;
+      }
+     
+      nBytes = s->numZ;
+      for (i = 0; i < 16; i++)
+         if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
+
+      for (i = 0; i < 16; i++)
+         if (inUse16[i])
+            for (j = 0; j < 16; j++) {
+               if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
+            }
+
+      if (s->verbosity >= 3) 
+         VPrintf1( "      bytes: mapping %d, ", s->numZ-nBytes );
+   }
+
+   /*--- Now the selectors. ---*/
+   nBytes = s->numZ;
+   bsW ( s, 3, nGroups );
+   bsW ( s, 15, nSelectors );
+   for (i = 0; i < nSelectors; i++) { 
+      for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
+      bsW(s,1,0);
+   }
+   if (s->verbosity >= 3)
+      VPrintf1( "selectors %d, ", s->numZ-nBytes );
+
+   /*--- Now the coding tables. ---*/
+   nBytes = s->numZ;
+
+   for (t = 0; t < nGroups; t++) {
+      Int32 curr = s->len[t][0];
+      bsW ( s, 5, curr );
+      for (i = 0; i < alphaSize; i++) {
+         while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
+         while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
+         bsW ( s, 1, 0 );
+      }
+   }
+
+   if (s->verbosity >= 3)
+      VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
+
+   /*--- And finally, the block data proper ---*/
+   nBytes = s->numZ;
+   selCtr = 0;
+   gs = 0;
+   while (True) {
+      if (gs >= s->nMTF) break;
+      ge = gs + BZ_G_SIZE - 1; 
+      if (ge >= s->nMTF) ge = s->nMTF-1;
+      AssertH ( s->selector[selCtr] < nGroups, 3006 );
+
+      if (nGroups == 6 && 50 == ge-gs+1) {
+            /*--- fast track the common case ---*/
+            UInt16 mtfv_i;
+            UChar* s_len_sel_selCtr 
+               = &(s->len[s->selector[selCtr]][0]);
+            Int32* s_code_sel_selCtr
+               = &(s->code[s->selector[selCtr]][0]);
+
+#           define BZ_ITAH(nn)                      \
+               mtfv_i = mtfv[gs+(nn)];              \
+               bsW ( s,                             \
+                     s_len_sel_selCtr[mtfv_i],      \
+                     s_code_sel_selCtr[mtfv_i] )
+
+            BZ_ITAH(0);  BZ_ITAH(1);  BZ_ITAH(2);  BZ_ITAH(3);  BZ_ITAH(4);
+            BZ_ITAH(5);  BZ_ITAH(6);  BZ_ITAH(7);  BZ_ITAH(8);  BZ_ITAH(9);
+            BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
+            BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
+            BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
+            BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
+            BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
+            BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
+            BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
+            BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
+
+#           undef BZ_ITAH
+
+      } else {
+	 /*--- slow version which correctly handles all situations ---*/
+         for (i = gs; i <= ge; i++) {
+            bsW ( s, 
+                  s->len  [s->selector[selCtr]] [mtfv[i]],
+                  s->code [s->selector[selCtr]] [mtfv[i]] );
+         }
+      }
+
+
+      gs = ge+1;
+      selCtr++;
+   }
+   AssertH( selCtr == nSelectors, 3007 );
+
+   if (s->verbosity >= 3)
+      VPrintf1( "codes %d\n", s->numZ-nBytes );
+   else /* squash compiler 'used but not set' warning */
+      nBytes = nBytes;
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_compressBlock ( EState* s, Bool is_last_block )
+{
+   if (s->nblock > 0) {
+
+      BZ_FINALISE_CRC ( s->blockCRC );
+      s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
+      s->combinedCRC ^= s->blockCRC;
+      if (s->blockNo > 1) s->numZ = 0;
+
+      if (s->verbosity >= 2)
+         VPrintf4( "    block %d: crc = 0x%08x, "
+                   "combined CRC = 0x%08x, size = %d\n",
+                   s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
+
+      BZ2_blockSort ( s );
+   }
+
+   s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
+
+   /*-- If this is the first block, create the stream header. --*/
+   if (s->blockNo == 1) {
+      BZ2_bsInitWrite ( s );
+      bsPutUChar ( s, BZ_HDR_B );
+      bsPutUChar ( s, BZ_HDR_Z );
+      bsPutUChar ( s, BZ_HDR_h );
+      bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
+   }
+
+   if (s->nblock > 0) {
+
+      bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
+      bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
+      bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
+
+      /*-- Now the block's CRC, so it is in a known place. --*/
+      bsPutUInt32 ( s, s->blockCRC );
+
+      /*-- 
+         Now a single bit indicating (non-)randomisation. 
+         As of version 0.9.5, we use a better sorting algorithm
+         which makes randomisation unnecessary.  So always set
+         the randomised bit to 'no'.  Of course, the decoder
+         still needs to be able to handle randomised blocks
+         so as to maintain backwards compatibility with
+         older versions of bzip2.
+      --*/
+      bsW(s,1,0);
+
+      bsW ( s, 24, s->origPtr );
+      generateMTFValues ( s );
+      sendMTFValues ( s );
+   }
+
+
+   /*-- If this is the last block, add the stream trailer. --*/
+   if (is_last_block) {
+
+      bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
+      bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
+      bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
+      bsPutUInt32 ( s, s->combinedCRC );
+      if (s->verbosity >= 2)
+         VPrintf1( "    final combined CRC = 0x%08x\n   ", s->combinedCRC );
+      bsFinishWrite ( s );
+   }
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                        compress.c ---*/
+/*-------------------------------------------------------------*/
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 05/18] dm: video: Add a video uclass
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (3 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 04/18] bzip2: Support compression for sandbox Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-17 18:35   ` Anatolij Gustschin
  2016-01-05 16:31 ` [U-Boot] [PATCH 06/18] dm: lcd: Avoid using the lcd.h header file with driver model Simon Glass
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

U-Boot has separate code for LCDs and 'video' devices. Both now use a
very similar API thanks to earlier work by Nikita Kiryanov. With the driver-
model conversion we should unify these into a single uclass.

Unfortunately there are different features supported by each. This
implementation provides for a common set of features which should serve
most purposes. The intent is to support:

- bitmap devices with 8, 16 and 32 bits per pixel
- text console wih white on black or vice versa
- rotated text console
- bitmap display (BMP format)

More can be added as additional boards are ported over to use driver model
for video.

The name 'video' is chosen for the uclass since it is more generic than LCD.
Another option would be 'display' but that would introduce a third concept
to U-Boot which seems like the wrong approach.

The existing LCD and video init functions are not needed now, so this uclass
makes no attempt to implement them.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/Kconfig        |  40 ++++++++
 drivers/video/Makefile       |   1 +
 drivers/video/video-uclass.c | 228 +++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h       |   1 +
 include/video.h              | 169 ++++++++++++++++++++++++++++++--
 5 files changed, 433 insertions(+), 6 deletions(-)
 create mode 100644 drivers/video/video-uclass.c

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index caf1efc..f17eb0a 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -4,6 +4,46 @@
 
 menu "Graphics support"
 
+config DM_VIDEO
+	bool "Enable driver model support for LCD/video"
+	depends on DM
+	help
+	  This enables driver model for LCD and video devices. These support
+	  a bitmap display of various sizes and depths which can be drawn on
+	  to display a command-line console or splash screen. Enabling this
+	  option compiles in the video uclass and routes all LCD/video access
+	  through this.
+
+config VIDEO_BPP8
+	bool "Support 8-bit-per-pixel displays"
+	depends on DM_VIDEO
+	default y if DM_VIDEO
+	help
+	  Support drawing text and bitmaps onto a 8-bit-per-pixel display.
+	  Ebabling this will include code to support this display. Without
+	  this option, such displays will not be supported and console output
+	  will be empty.
+
+config VIDEO_BPP16
+	bool "Support 16-bit-per-pixel displays"
+	depends on DM_VIDEO
+	default y if DM_VIDEO
+	help
+	  Support drawing text and bitmaps onto a 16-bit-per-pixel display.
+	  Ebabling this will include code to support this display. Without
+	  this option, such displays will not be supported and console output
+	  will be empty.
+
+config VIDEO_BPP32
+	bool "Support 32-bit-per-pixel displays"
+	depends on DM_VIDEO
+	default y if DM_VIDEO
+	help
+	  Support drawing text and bitmaps onto a 32-bit-per-pixel display.
+	  Ebabling this will include code to support this display. Without
+	  this option, such displays will not be supported and console output
+	  will be empty.
+
 config VIDEO_VESA
 	bool "Enable VESA video driver support"
 	default n
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index e85fd8a..7192013 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -7,6 +7,7 @@
 
 ifdef CONFIG_DM
 obj-$(CONFIG_DISPLAY_PORT) += dp-uclass.o
+obj-$(CONFIG_DM_VIDEO) += video-uclass.o
 endif
 
 obj-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
new file mode 100644
index 0000000..1615889
--- /dev/null
+++ b/drivers/video/video-uclass.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdio_dev.h>
+#include <video.h>
+#include <video_console.h>
+#include <dm/lists.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#ifdef CONFIG_SANDBOX
+#include <asm/sdl.h>
+#endif
+
+/*
+ * Theory of operation:
+ *
+ * Before relocation each device is bound. The driver for each device must
+ * set the @align and @size values in struct video_uc_platdata. This
+ * information represents the requires size and alignment of the frame buffer
+ * for the device. The values can be an over-estimate but cannot be too
+ * small. The actual values will be suppled (in the same manner) by the bind()
+ * method after relocation.
+ *
+ * This information is then picked up by video_reserve() which works out how
+ * much memory is needed for all devices. This is allocated between
+ * gd->video_bottom and gd->video_top.
+ *
+ * After relocation the same process occurs. The driver supplies the same
+ * @size and @align information and this time video_post_bind() checks that
+ * the drivers does not overflow the allocated memory.
+ *
+ * The frame buffer address is actually set (to plat->base) in
+ * video_post_probe(). This function also clears the frame buffer and
+ * allocates a suitable text console device. This can then be used to write
+ * text to the video device.
+ */
+DECLARE_GLOBAL_DATA_PTR;
+
+static ulong alloc_fb(struct udevice *dev, ulong *addrp)
+{
+	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+	ulong base, align, size;
+
+	align = plat->align ? plat->align : 1 << 20;
+	base = *addrp - plat->size;
+	base &= ~(align - 1);
+	plat->base = base;
+	size = *addrp - base;
+	*addrp = base;
+
+	return size;
+}
+
+int video_reserve(ulong *addrp)
+{
+	struct udevice *dev;
+	ulong size;
+
+	gd->video_top = *addrp;
+	for (uclass_find_first_device(UCLASS_VIDEO, &dev);
+	     dev;
+	     uclass_find_next_device(&dev)) {
+		size = alloc_fb(dev, addrp);
+		debug("%s: Reserving %lx bytes at %lx for video device '%s'\n",
+		      __func__, size, *addrp, dev->name);
+	}
+	gd->video_bottom = *addrp;
+	debug("Video frame buffers from %lx to %lx\n", gd->video_bottom,
+	      gd->video_top);
+
+	return 0;
+}
+
+static int video_clear(struct udevice *dev)
+{
+	struct video_priv *priv = dev_get_uclass_priv(dev);
+
+	if (priv->bpix == VIDEO_BPP32) {
+		u32 *ppix = priv->fb;
+		u32 *end = priv->fb + priv->fb_size;
+
+		while (ppix < end)
+			*ppix++ = priv->colour_bg;
+	} else {
+		memset(priv->fb, priv->colour_bg, priv->fb_size);
+	}
+
+	return 0;
+}
+
+/* Flush video activity to the caches */
+void video_sync(struct udevice *vid)
+{
+	/*
+	 * flush_dcache_range() is declared in common.h but it seems that some
+	 * architectures do not actually implement it. Is there a way to find
+	 * out whether it exists? For now, ARM is safe.
+	 */
+#if defined(CONFIG_ARM) && !defined(CONFIG_SYS_DCACHE_OFF)
+	struct video_priv *priv = dev_get_uclass_priv(vid);
+
+	if (priv->flush_dcache) {
+		flush_dcache_range((ulong)priv->fb,
+				   (ulong)priv->fb + priv->fb_size);
+	}
+#elif defined(CONFIG_VIDEO_SANDBOX_SDL)
+	struct video_priv *priv = dev_get_uclass_priv(vid);
+	static ulong last_sync;
+
+	if (get_timer(last_sync) > 10) {
+		sandbox_sdl_sync(priv->fb);
+		last_sync = get_timer(0);
+	}
+#endif
+}
+
+void video_sync_all(void)
+{
+	struct udevice *dev;
+
+	for (uclass_find_first_device(UCLASS_VIDEO, &dev);
+	     dev;
+	     uclass_find_next_device(&dev)) {
+		if (device_active(dev))
+			video_sync(dev);
+	}
+}
+
+int video_get_xsize(struct udevice *dev)
+{
+	struct video_priv *priv = dev_get_uclass_priv(dev);
+
+	return priv->xsize;
+}
+
+int video_get_ysize(struct udevice *dev)
+{
+	struct video_priv *priv = dev_get_uclass_priv(dev);
+
+	return priv->ysize;
+}
+
+/* Set up the colour map */
+static int video_pre_probe(struct udevice *dev)
+{
+	struct video_priv *priv = dev_get_uclass_priv(dev);
+
+	priv->cmap = calloc(256, sizeof(ushort));
+	if (!priv->cmap)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int video_pre_remove(struct udevice *dev)
+{
+	struct video_priv *priv = dev_get_uclass_priv(dev);
+
+	free(priv->cmap);
+
+	return 0;
+}
+
+/* Set up the display ready for use */
+static int video_post_probe(struct udevice *dev)
+{
+	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+	struct video_priv *priv = dev_get_uclass_priv(dev);
+	char name[30], drv[15], *str;
+	struct udevice *cons;
+	int ret;
+
+	/* Set up the line and display size */
+	priv->fb = map_sysmem(plat->base, plat->size);
+	priv->line_length = priv->xsize * VNBYTES(priv->bpix);
+	priv->fb_size = priv->line_length * priv->ysize;
+
+	/* Set up colours - we could in future support other colours */
+#ifdef CONFIG_SYS_WHITE_ON_BLACK
+	priv->colour_fg = 0xffffff;
+#else
+	priv->colour_bg = 0xffffff;
+#endif
+	video_clear(dev);
+
+	return 0;
+};
+
+/* Post-relocation, allocate memory for the frame buffer */
+static int video_post_bind(struct udevice *dev)
+{
+	ulong addr = gd->video_top;
+	ulong size;
+
+	/* Before relocation there is nothing to do here */
+	if ((!gd->flags & GD_FLG_RELOC))
+		return 0;
+	size = alloc_fb(dev, &addr);
+	if (addr < gd->video_bottom) {
+		/* Device tree node may need the 'u-boot,dm-pre-reloc' tag */
+		printf("Video device '%s' cannot allocate frame buffer memory -ensure the device is set up before relocation\n",
+		       dev->name);
+		return -ENOSPC;
+	}
+	debug("%s: Claiming %lx bytes at %lx for video device '%s'\n",
+	      __func__, size, addr, dev->name);
+	gd->video_bottom = addr;
+
+	return 0;
+}
+
+UCLASS_DRIVER(video) = {
+	.id		= UCLASS_VIDEO,
+	.name		= "video",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
+	.post_bind	= video_post_bind,
+	.pre_probe	= video_pre_probe,
+	.post_probe	= video_post_probe,
+	.pre_remove	= video_pre_remove,
+	.per_device_auto_alloc_size	= sizeof(struct video_priv),
+	.per_device_platdata_auto_alloc_size = sizeof(struct video_uc_platdata),
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 27fa0b6..3934375 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -66,6 +66,7 @@ enum uclass_id {
 	UCLASS_USB,		/* USB bus */
 	UCLASS_USB_DEV_GENERIC,	/* USB generic device */
 	UCLASS_USB_HUB,		/* USB hub */
+	UCLASS_VIDEO,		/* Video or LCD device */
 	UCLASS_VIDEO_BRIDGE,	/* Video bridge, e.g. DisplayPort to LVDS */
 
 	UCLASS_COUNT,
diff --git a/include/video.h b/include/video.h
index 65e4ec1..5fd426e 100644
--- a/include/video.h
+++ b/include/video.h
@@ -1,14 +1,168 @@
 /*
-** MPC823 Video Controller
-** =======================
-** (C) 2000 by Paolo Scaffardi (arsenio at tin.it)
-** AIRVENT SAM s.p.a - RIMINI(ITALY)
-**
-*/
+ * Video uclass and legacy implementation
+ *
+ * Copyright (c) 2015 Google, Inc
+ *
+ * MPC823 Video Controller
+ * =======================
+ * (C) 2000 by Paolo Scaffardi (arsenio at tin.it)
+ * AIRVENT SAM s.p.a - RIMINI(ITALY)
+ *
+ */
 
 #ifndef _VIDEO_H_
 #define _VIDEO_H_
 
+#ifdef CONFIG_DM_VIDEO
+
+#include <stdio_dev.h>
+
+struct video_uc_platdata {
+	uint align;
+	uint size;
+	ulong base;
+};
+
+/*
+ * Bits per pixel selector. Each value n is such that the bits-per-pixel is
+ * 2 ^ n
+ */
+enum video_log2_bpp {
+	VIDEO_BPP1	= 0,
+	VIDEO_BPP2,
+	VIDEO_BPP4,
+	VIDEO_BPP8,
+	VIDEO_BPP16,
+	VIDEO_BPP32,
+};
+
+/*
+ * Convert enum video_log2_bpp to bytes and bits. Note we omit the outer
+ * brackets to allow multiplication by fractional pixels.
+ */
+#define VNBYTES(bpix)	(1 << (bpix)) / 8
+
+#define VNBITS(bpix)	(1 << (bpix))
+
+/**
+ * struct video_priv - Device information used by the video uclass
+ *
+ * @xsize:	Number of pixel columns (e.g. 1366)
+ * @ysize:	Number of pixels rows (e.g.. 768)
+ * @tor:	Display rotation (0=none, 1=90 degrees clockwise, etc.)
+ * @bpix:	Encoded bits per pixel
+ * @fb:		Frame buffer
+ * @fb_size:	Frame buffer size
+ * @fb_size:	Frame buffer size
+ * @line_length:	Length of each frame buffer line, in bytes
+ * @colour_fg:	Foreground colour (pixel value)
+ * @colour_bg:	Background colour (pixel value)
+ * @flush_dcache:	true to enable flushing of the data cache after
+ *		the LCD is updated
+ * @cmap:	Colour map for 8-bit-per-pixel displays
+ */
+struct video_priv {
+	/* Things set up by the driver: */
+	ushort xsize;
+	ushort ysize;
+	ushort rot;
+	enum video_log2_bpp bpix;
+
+	/*
+	 * Things that are private to the uclass: don't use these in the
+	 * driver
+	 */
+	void *fb;
+	int fb_size;
+	int line_length;
+	int colour_fg;
+	int colour_bg;
+	bool flush_dcache;
+	ushort *cmap;
+};
+
+/* Placeholder - there are no video operations@present */
+struct video_ops {
+};
+
+#define video_get_ops(dev)        ((struct video_ops *)(dev)->driver->ops)
+
+/**
+ * video_reserve() - Reserve frame-buffer memory for video devices
+ *
+ * Note: This function is for internal use.
+ *
+ * This uses the uclass platdata's @size and @align members to figure out
+ * a size and position for each frame buffer as part of the pre-relocation
+ * process of determining the post-relocation memory layout.
+ *
+ * gd->video_top is set to the initial value of *@addrp and gd->video_bottom
+ * is set to the final value.
+ *
+ * @addrp:	On entry, the top of available memory. On exit, the new top,
+ *		after allocating the required memory.
+ * @return 0
+ */
+int video_reserve(ulong *addrp);
+
+/**
+ * video_sync() - Sync a device's frame buffer with its hardware
+ *
+ * Some frame buffers are cached or have a secondary frame buffer. This
+ * function syncs these up so that the current contents of the U-Boot frame
+ * buffer are displayed to the user.
+ *
+ * @dev:	Device to sync
+ */
+void video_sync(struct udevice *vid);
+
+/**
+ * video_sync_all() - Sync all devices' frame buffers with there hardware
+ *
+ * This calls video_sync() on all active video devices.
+ */
+void video_sync_all(void);
+
+/**
+ * video_bmp_display() - Display a BMP file
+ *
+ * @dev:	Device to display the bitmap on
+ * @bmp_image:	Address of bitmap image to display
+ * @x:		X position in pixels from the left
+ * @y:		Y position in pixels from the top
+ * @align:	true to adjust the coordinates to centre the image. If false
+ *		the coordinates are used as is. If true:
+ * 
+ *		- if a coordinate is 0x7fff then the image will be centred in
+ *		  that direction
+ *		- if a coordinate is -ve then it will be offset to the
+ *		  left/top of the centre by that many pixels
+ *		- if a coordinate is positive it will be used unchnaged.
+ * @return 0 if OK, -ve on error
+ */
+int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
+		      bool align);
+
+/**
+ * video_get_xsize() - Get the width of the display in pixels
+ *
+ * @dev:	Device to check
+ * @return device frame buffer width in pixels
+ */
+int video_get_xsize(struct udevice *dev);
+
+/**
+ * video_get_xsize() - Get the height of the display in pixels
+ *
+ * @dev:	Device to check
+ * @return device frame buffer height in pixels
+ */
+int video_get_ysize(struct udevice *dev);
+
+#endif /* CONFIG_DM_VIDEO */
+
+#ifndef CONFIG_DM_VIDEO
+
 /* Video functions */
 
 struct stdio_dev;
@@ -73,4 +227,7 @@ int kwh043st20_f01_spi_startup(unsigned int bus, unsigned int cs,
 int lg4573_spi_startup(unsigned int bus, unsigned int cs,
 	unsigned int max_hz, unsigned int spi_mode);
 #endif
+
+#endif /* CONFIG_DM_VIDEO */
+
 #endif
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 06/18] dm: lcd: Avoid using the lcd.h header file with driver model
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (4 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 05/18] dm: video: Add a video uclass Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-17 18:40   ` Anatolij Gustschin
  2016-01-05 16:31 ` [U-Boot] [PATCH 07/18] dm: video: Add a uclass for the text console Simon Glass
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

The LCD functions and definitions are not used with the driver model video
uclass. When all boards are converted over we can remove the file. For now,
use #ifdef to omit the contents.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 common/Makefile |  2 ++
 include/lcd.h   | 12 ++++++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/common/Makefile b/common/Makefile
index 2a1d9f8..2492275 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -205,7 +205,9 @@ obj-$(CONFIG_I2C_EDID) += edid.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
 obj-y += splash.o
 obj-$(CONFIG_SPLASH_SOURCE) += splash_source.o
+ifndef CONFIG_DM_VIDEO
 obj-$(CONFIG_LCD) += lcd.o lcd_console.o
+endif
 obj-$(CONFIG_LCD_ROTATION) += lcd_console_rotation.o
 obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o
 obj-$(CONFIG_LYNXKDI) += lynxkdi.o
diff --git a/include/lcd.h b/include/lcd.h
index 59202b7..d7651a8 100644
--- a/include/lcd.h
+++ b/include/lcd.h
@@ -18,6 +18,12 @@
 #include <asm/byteorder.h>
 #endif
 
+int bmp_display(ulong addr, int x, int y);
+struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
+			     void **alloc_addr);
+
+#ifndef CONFIG_DM_VIDEO
+
 extern char lcd_is_enabled;
 extern int lcd_line_length;
 extern struct vidinfo panel_info;
@@ -26,10 +32,6 @@ void lcd_ctrl_init(void *lcdbase);
 void lcd_enable(void);
 void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue);
 
-struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
-			     void **alloc_addr);
-int bmp_display(ulong addr, int x, int y);
-
 /**
  * Set whether we need to flush the dcache when changing the LCD image. This
  * defaults to off.
@@ -209,4 +211,6 @@ void lcd_sync(void);
 #define PAGE_SIZE	4096
 #endif
 
+#endif /* !CONFIG_DM_VIDEO */
+
 #endif	/* _LCD_H_ */
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 07/18] dm: video: Add a uclass for the text console
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (5 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 06/18] dm: lcd: Avoid using the lcd.h header file with driver model Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-17 19:09   ` Anatolij Gustschin
  2016-01-05 16:31 ` [U-Boot] [PATCH 08/18] dm: video: Add a 'normal' text console driver Simon Glass
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

The existing LCD/video interface suffers from conflating the bitmap display
with text output on that display. As a result the implementation is more
complex than it needs to me.

We can support multiple text console drivers. Create a separate uclass to
support this, with its own API.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/Makefile            |   2 +-
 drivers/video/vidconsole-uclass.c | 239 ++++++++++++++++++++++++++++++++++++++
 drivers/video/video-uclass.c      |  21 ++++
 include/dm/uclass-id.h            |   1 +
 include/video_console.h           | 136 ++++++++++++++++++++++
 5 files changed, 398 insertions(+), 1 deletion(-)
 create mode 100644 drivers/video/vidconsole-uclass.c
 create mode 100644 include/video_console.h

diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 7192013..e82f1ae 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -7,7 +7,7 @@
 
 ifdef CONFIG_DM
 obj-$(CONFIG_DISPLAY_PORT) += dp-uclass.o
-obj-$(CONFIG_DM_VIDEO) += video-uclass.o
+obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o
 endif
 
 obj-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
new file mode 100644
index 0000000..ea10189
--- /dev/null
+++ b/drivers/video/vidconsole-uclass.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * (C) Copyright 2001-2015
+ * DENX Software Engineering -- wd at denx.de
+ * Compulab Ltd - http://compulab.co.il/
+ * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <video.h>
+#include <video_console.h>
+#include <video_font.h>		/* Get font data, width and height */
+
+/* By default we scroll by a single line */
+#ifndef CONFIG_CONSOLE_SCROLL_LINES
+#define CONFIG_CONSOLE_SCROLL_LINES 1
+#endif
+
+int vidconsole_putc_xy(struct udevice *dev, uint x, uint y, char ch)
+{
+	struct vidconsole_ops *ops = vidconsole_get_ops(dev);
+
+	if (!ops->putc_xy)
+		return -ENOSYS;
+	return ops->putc_xy(dev, x, y, ch);
+}
+
+int vidconsole_move_rows(struct udevice *dev, uint rowdst, uint rowsrc,
+			 uint count)
+{
+	struct vidconsole_ops *ops = vidconsole_get_ops(dev);
+
+	if (!ops->move_rows)
+		return -ENOSYS;
+	return ops->move_rows(dev, rowdst, rowsrc, count);
+}
+
+int vidconsole_set_row(struct udevice *dev, uint row, int clr)
+{
+	struct vidconsole_ops *ops = vidconsole_get_ops(dev);
+
+	if (!ops->set_row)
+		return -ENOSYS;
+	return ops->set_row(dev, row, clr);
+}
+
+/* Move backwards one space */
+static void vidconsole_back(struct udevice *dev)
+{
+	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
+
+	if (--priv->curr_col < 0) {
+		priv->curr_col = priv->cols - 1;
+		if (--priv->curr_row < 0)
+			priv->curr_row = 0;
+	}
+
+	vidconsole_putc_xy(dev, priv->curr_col * VIDEO_FONT_WIDTH,
+			   priv->curr_row * VIDEO_FONT_HEIGHT, ' ');
+}
+
+/* Move to a newline, scrolling the display if necessary */
+static void vidconsole_newline(struct udevice *dev)
+{
+	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
+	struct udevice *vid_dev = dev->parent;
+	struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
+	const int rows = CONFIG_CONSOLE_SCROLL_LINES;
+	int i;
+
+	priv->curr_col = 0;
+
+	/* Check if we need to scroll the terminal */
+	if (++priv->curr_row >= priv->rows) {
+		vidconsole_move_rows(dev, 0, rows, priv->rows - rows);
+		for (i = 0; i < rows; i++)
+			vidconsole_set_row(dev, priv->rows - i - 1,
+					   vid_priv->colour_bg);
+		priv->curr_row -= rows;
+	}
+	video_sync(dev->parent);
+}
+
+int vidconsole_put_char(struct udevice *dev, char ch)
+{
+	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
+	int ret;
+
+	switch (ch) {
+	case '\r':
+		priv->curr_col = 0;
+		break;
+	case '\n':
+		vidconsole_newline(dev);
+		break;
+	case '\t':	/* Tab (8 chars alignment) */
+		priv->curr_col +=  8;
+		priv->curr_col &= ~7;
+
+		if (priv->curr_col >= priv->cols)
+			vidconsole_newline(dev);
+		break;
+	case '\b':
+		vidconsole_back(dev);
+		break;
+	default:
+		/*
+		 * Failure of this function normally indicates an unsupported
+		 * colour depth. Check this and return an error to help with
+		 * diagnosis.
+		 */
+		ret = vidconsole_putc_xy(dev,
+					 priv->curr_col * VIDEO_FONT_WIDTH,
+					 priv->curr_row * VIDEO_FONT_HEIGHT,
+					 ch);
+		if (ret)
+			return ret;
+		if (++priv->curr_col >= priv->cols)
+			vidconsole_newline(dev);
+		break;
+	}
+
+	return 0;
+}
+
+static void vidconsole_putc(struct stdio_dev *sdev, const char ch)
+{
+	struct udevice *dev = sdev->priv;
+
+	vidconsole_put_char(dev, ch);
+}
+
+static void vidconsole_puts(struct stdio_dev *sdev, const char *s)
+{
+	struct udevice *dev = sdev->priv;
+
+	while (*s)
+		vidconsole_put_char(dev, *s++);
+}
+
+/* Set up the number of rows and colours (rotated drivers override this) */
+static int vidconsole_pre_probe(struct udevice *dev)
+{
+	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
+	struct udevice *vid = dev->parent;
+	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
+
+	priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT;
+	priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH;
+
+	return 0;
+}
+
+/* Register the device with stdio */
+static int vidconsole_post_probe(struct udevice *dev)
+{
+	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
+	struct stdio_dev *sdev = &priv->sdev;
+	int ret;
+
+	strlcpy(sdev->name, dev->name, sizeof(sdev->name));
+	sdev->flags = DEV_FLAGS_OUTPUT;
+	sdev->putc = vidconsole_putc;
+	sdev->puts = vidconsole_puts;
+	sdev->priv = dev;
+	ret = stdio_register(sdev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+UCLASS_DRIVER(vidconsole) = {
+	.id		= UCLASS_VIDEO_CONSOLE,
+	.name		= "vidconsole0",
+	.pre_probe	= vidconsole_pre_probe,
+	.post_probe	= vidconsole_post_probe,
+	.per_device_auto_alloc_size	= sizeof(struct vidconsole_priv),
+};
+
+void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row)
+{
+	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
+
+	priv->curr_col = min_t(short, col, priv->cols - 1);
+	priv->curr_row = min_t(short, row, priv->rows - 1);
+}
+
+static int do_video_setcursor(cmd_tbl_t *cmdtp, int flag, int argc,
+			      char *const argv[])
+{
+	unsigned int col, row;
+	struct udevice *dev;
+
+	if (argc != 3)
+		return CMD_RET_USAGE;
+
+	uclass_first_device(UCLASS_VIDEO_CONSOLE, &dev);
+	if (!dev)
+		return CMD_RET_FAILURE;
+	col = simple_strtoul(argv[1], NULL, 10);
+	row = simple_strtoul(argv[2], NULL, 10);
+	vidconsole_position_cursor(dev, col, row);
+
+	return 0;
+}
+
+static int do_video_puts(cmd_tbl_t *cmdtp, int flag, int argc,
+			 char *const argv[])
+{
+	struct udevice *dev;
+	const char *s;
+
+	if (argc != 2)
+		return CMD_RET_USAGE;
+
+	uclass_first_device(UCLASS_VIDEO_CONSOLE, &dev);
+	if (!dev)
+		return CMD_RET_FAILURE;
+	for (s = argv[1]; *s; s++)
+		vidconsole_put_char(dev, *s);
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	setcurs, 3,	1,	do_video_setcursor,
+	"set cursor position within screen",
+	"    <col> <row> in character"
+);
+
+U_BOOT_CMD(
+	lcdputs, 2,	1,	do_video_puts,
+	"print string on video framebuffer",
+	"    <string>"
+);
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index 1615889..63d0d9d 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -189,6 +189,27 @@ static int video_post_probe(struct udevice *dev)
 #endif
 	video_clear(dev);
 
+	/*
+	 * Create a text console devices. For now we always do this, although
+	 * it might be useful to support only bitmap drawing on the device
+	 * for boards that don't need to display text.
+	 */
+	snprintf(name, sizeof(name), "%s.vidconsole", dev->name);
+	str = strdup(name);
+	if (!str)
+		return -ENOMEM;
+	snprintf(drv, sizeof(drv), "vidconsole%d", priv->rot);
+	ret = device_bind_driver(dev, drv, str, &cons);
+	if (ret) {
+		debug("%s: Cannot bind console driver\n", __func__);
+		return ret;
+	}
+	ret = device_probe(cons);
+	if (ret) {
+		debug("%s: Cannot probe console driver\n", __func__);
+		return ret;
+	}
+
 	return 0;
 };
 
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 3934375..a0a3a79 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -68,6 +68,7 @@ enum uclass_id {
 	UCLASS_USB_HUB,		/* USB hub */
 	UCLASS_VIDEO,		/* Video or LCD device */
 	UCLASS_VIDEO_BRIDGE,	/* Video bridge, e.g. DisplayPort to LVDS */
+	UCLASS_VIDEO_CONSOLE,	/* Text console driver for video device */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/video_console.h b/include/video_console.h
new file mode 100644
index 0000000..d4acbc8
--- /dev/null
+++ b/include/video_console.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __video_console_h
+#define __video_console_h
+
+/**
+ * struct vidconsole_priv - uclass-private data about a console device
+ *
+ * @sdev:	stdio device, acting as an output sink
+ * @curr_col:	Current text column (0=left)
+ * @curr_row:	Current row (0=top)
+ * @rows:	Number of text rows
+ * @cols:	Number of text columns
+ */
+struct vidconsole_priv {
+	struct stdio_dev sdev;
+	int curr_col;
+	int curr_row;
+	int rows;
+	int cols;
+};
+
+/**
+ * struct vidconsole_ops - Video console operations
+ *
+ * These operations work on either an absolute console position (measured
+ * in pixels) or a text row number (measured in rows, where each row consists
+ * of an entire line of text - typically 16 pixels).
+ */
+struct vidconsole_ops {
+	/**
+	 * putc_xy() - write a single character to a position
+	 *
+	 * @dev:	Device to write to
+	 * @x:		Pixel X position (0=left-most pixel)
+	 * @y:		Pixel Y position (0=top-most pixel)
+	 * @ch:		Character to write
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*putc_xy)(struct udevice *dev, uint x, uint y, char ch);
+
+	/**
+	 * move_rows() - Move text rows from one place to another
+	 *
+	 * @dev:	Device to adjust
+	 * @rowdst:	Destination text row (0=top)
+	 * @rowsrc:	Source start text row
+	 * @count:	Number of text rows to move
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*move_rows)(struct udevice *dev, uint rowdst, uint rowsrc,
+			  uint count);
+
+	/**
+	 * set_row() - Set the colour of a text row
+	 *
+	 * Every pixel contained within the text row is adjusted
+	 *
+	 * @dev:	Device to adjust
+	 * @row:	Text row to adjust (0=top)
+	 * @clr:	Raw colour (pixel value) to write to each pixel
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*set_row)(struct udevice *dev, uint row, int clr);
+};
+
+/* Get a pointer to the driver operations for a video console device */
+#define vidconsole_get_ops(dev)  ((struct vidconsole_ops *)(dev)->driver->ops)
+
+/**
+ * vidconsole_putc_xy() - write a single character to a position
+ *
+ * @dev:	Device to write to
+ * @x:		Pixel X position (0=left-most pixel)
+ * @y:		Pixel Y position (0=top-most pixel)
+ * @ch:		Character to write
+ * @return 0 if OK, -ve on error
+ */
+int vidconsole_putc_xy(struct udevice *dev, uint x, uint y, char ch);
+
+/**
+ * vidconsole_move_rows() - Move text rows from one place to another
+ *
+ * @dev:	Device to adjust
+ * @rowdst:	Destination text row (0=top)
+ * @rowsrc:	Source start text row
+ * @count:	Number of text rows to move
+ * @return 0 if OK, -ve on error
+ */
+int vidconsole_move_rows(struct udevice *dev, uint rowdst, uint rowsrc,
+			 uint count);
+
+/**
+ * vidconsole_set_row() - Set the colour of a text row
+ *
+ * Every pixel contained within the text row is adjusted
+ *
+ * @dev:	Device to adjust
+ * @row:	Text row to adjust (0=top)
+ * @clr:	Raw colour (pixel value) to write to each pixel
+ * @return 0 if OK, -ve on error
+ */
+int vidconsole_set_row(struct udevice *dev, uint row, int clr);
+
+/**
+ * vidconsole_put_char() - Output a character to the current console position
+ *
+ * Outputs a character to the console and advances the cursor. This function
+ * handles wrapping to new lines and scrolling the console. Special
+ * characters are handled also: \n, \r, \n and \t.
+ *
+ * The device always starts withthe cursor at position 0,0 (top left). It
+ * can be adjusted manually using vidconsole_position_cursor().
+ *
+ * @dev:	Device to adjust
+ * @ch:		Character to write
+ * @return 0 if OK, -ve on error
+ */
+int vidconsole_put_char(struct udevice *dev, char ch);
+
+/**
+ * vidconsole_position_cursor() - Move the text cursor
+ *
+ * @dev:	Device to adjust
+ * @col:	New cursor text column
+ * @row:	New cursor text row
+ * @return 0 if OK, -ve on error
+ */
+void vidconsole_position_cursor(struct udevice *dev, unsigned col,
+				unsigned row);
+
+#endif
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 08/18] dm: video: Add a 'normal' text console driver
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (6 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 07/18] dm: video: Add a uclass for the text console Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-17 20:04   ` Anatolij Gustschin
  2016-01-05 16:31 ` [U-Boot] [PATCH 09/18] dm: video: Add a driver for a rotated text console Simon Glass
                   ` (10 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

Most of the time we don't need to rotate the display so a simple font
blitting feature is enough for our purposes. Add a simple driver which
supports this function. It provides text output on the console using
the standard 8x16-pixel font.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/Makefile         |   2 +-
 drivers/video/console_normal.c | 141 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 142 insertions(+), 1 deletion(-)
 create mode 100644 drivers/video/console_normal.c

diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index e82f1ae..b4eba8e 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -7,7 +7,7 @@
 
 ifdef CONFIG_DM
 obj-$(CONFIG_DISPLAY_PORT) += dp-uclass.o
-obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o
+obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o console_normal.o
 endif
 
 obj-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o
diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c
new file mode 100644
index 0000000..d1031c8
--- /dev/null
+++ b/drivers/video/console_normal.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * (C) Copyright 2001-2015
+ * DENX Software Engineering -- wd at denx.de
+ * Compulab Ltd - http://compulab.co.il/
+ * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <video.h>
+#include <video_console.h>
+#include <video_font.h>		/* Get font data, width and height */
+
+static int console_normal_set_row(struct udevice *dev, uint row, int clr)
+{
+	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+	void *line;
+	int pixels = VIDEO_FONT_HEIGHT * vid_priv->line_length;
+	int i;
+
+	line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * vid_priv->line_length;
+	switch (vid_priv->bpix) {
+#ifdef CONFIG_VIDEO_BPP8
+	case VIDEO_BPP8: {
+		uint8_t *dst = line;
+
+		for (i = 0; i < pixels; i++)
+			*dst++ = clr;
+		break;
+	}
+#endif
+#ifdef CONFIG_VIDEO_BPP16
+	case VIDEO_BPP16: {
+		uint16_t *dst = line;
+
+		for (i = 0; i < pixels; i++)
+			*dst++ = clr;
+		break;
+	}
+#endif
+#ifdef CONFIG_VIDEO_BPP32
+	case VIDEO_BPP32: {
+		uint32_t *dst = line;
+
+		for (i = 0; i < pixels; i++)
+			*dst++ = clr;
+		break;
+	}
+#endif
+	default:
+		return -ENOSYS;
+	}
+
+	return 0;
+}
+
+static int console_normal_move_rows(struct udevice *dev, uint rowdst,
+				     uint rowsrc, uint count)
+{
+	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+	void *dst;
+	void *src;
+
+	dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * vid_priv->line_length;
+	src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * vid_priv->line_length;
+	memmove(dst, src, VIDEO_FONT_HEIGHT * vid_priv->line_length * count);
+
+	return 0;
+}
+
+static int console_normal_putc_xy(struct udevice *dev, uint x, uint y, char ch)
+{
+	struct udevice *vid = dev->parent;
+	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
+	int i, row;
+	void *line = vid_priv->fb + y * vid_priv->line_length +
+		x * VNBYTES(vid_priv->bpix);
+
+	for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
+		uchar bits = video_fontdata[ch * VIDEO_FONT_HEIGHT + row];
+
+		switch (vid_priv->bpix) {
+#ifdef CONFIG_VIDEO_BPP8
+		case VIDEO_BPP8: {
+			uint8_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
+				*dst++ = (bits & 0x80) ? vid_priv->colour_fg
+					: vid_priv->colour_bg;
+				bits <<= 1;
+			}
+			break;
+		}
+#endif
+#ifdef CONFIG_VIDEO_BPP16
+		case VIDEO_BPP16: {
+			uint16_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
+				*dst++ = (bits & 0x80) ? vid_priv->colour_fg
+					: vid_priv->colour_bg;
+				bits <<= 1;
+			}
+			break;
+		}
+#endif
+#ifdef CONFIG_VIDEO_BPP32
+		case VIDEO_BPP32: {
+			uint32_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
+				*dst++ = (bits & 0x80) ? vid_priv->colour_fg
+					: vid_priv->colour_bg;
+				bits <<= 1;
+			}
+			break;
+		}
+#endif
+		default:
+			return -ENOSYS;
+		}
+		line += vid_priv->line_length;
+	}
+
+	return 0;
+}
+
+struct vidconsole_ops console_normal_ops = {
+	.putc_xy	= console_normal_putc_xy,
+	.move_rows	= console_normal_move_rows,
+	.set_row	= console_normal_set_row,
+};
+
+U_BOOT_DRIVER(vidconsole_normal) = {
+	.name	= "vidconsole0",
+	.id	= UCLASS_VIDEO_CONSOLE,
+	.ops	= &console_normal_ops,
+};
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 09/18] dm: video: Add a driver for a rotated text console
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (7 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 08/18] dm: video: Add a 'normal' text console driver Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-17 20:07   ` Anatolij Gustschin
  2016-01-05 16:31 ` [U-Boot] [PATCH 10/18] common: Move LCD and video memory reservation together Simon Glass
                   ` (9 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

Sometimes the console must be rotated. Add a driver which supports rotating
the text clockwise to 90, 180 and 270 degrees. This can support devices
where the display is rotated for mechanical reasons.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/Kconfig          |  13 ++
 drivers/video/Makefile         |   1 +
 drivers/video/console_rotate.c | 435 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 449 insertions(+)
 create mode 100644 drivers/video/console_rotate.c

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index f17eb0a..39df24e 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -44,6 +44,19 @@ config VIDEO_BPP32
 	  this option, such displays will not be supported and console output
 	  will be empty.
 
+config VIDEO_ROTATION
+	bool "Support rotated displays"
+	depends on DM_VIDEO
+	help
+	  Sometimes, for example if the display is mounted in portrait
+	  mode or even if it's mounted landscape but rotated by 180degree,
+	  we need to rotate our content of the display relative to the
+	  framebuffer, so that user can read the messages which are
+	  printed out. Enable this option to include a text driver which can
+	  support this. The rotation is set by the 'rot' parameter in
+	  struct video_priv: 0=unrotated, 1=90 degrees clockwise, 2=180
+	  degrees, 3=270 degrees.
+
 config VIDEO_VESA
 	bool "Enable VESA video driver support"
 	default n
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index b4eba8e..8f26d1d 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -8,6 +8,7 @@
 ifdef CONFIG_DM
 obj-$(CONFIG_DISPLAY_PORT) += dp-uclass.o
 obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o console_normal.o
+obj-$(CONFIG_VIDEO_ROTATION) += console_rotate.o
 endif
 
 obj-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o
diff --git a/drivers/video/console_rotate.c b/drivers/video/console_rotate.c
new file mode 100644
index 0000000..4c5c4ef
--- /dev/null
+++ b/drivers/video/console_rotate.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * (C) Copyright 2015
+ * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <video.h>
+#include <video_console.h>
+#include <video_font.h>		/* Get font data, width and height */
+
+static int console_set_row_1(struct udevice *dev, uint row, int clr)
+{
+	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+	int pbytes = VNBYTES(vid_priv->bpix);
+	void *line;
+	int i, j;
+
+	line = vid_priv->fb + vid_priv->line_length -
+		(row + 1) * VIDEO_FONT_HEIGHT * pbytes;
+	for (j = 0; j < vid_priv->ysize; j++) {
+		switch (vid_priv->bpix) {
+#ifdef CONFIG_VIDEO_BPP8
+		case VIDEO_BPP8: {
+			uint8_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
+				*dst++ = clr;
+			break;
+		}
+#endif
+#ifdef CONFIG_VIDEO_BPP16
+		case VIDEO_BPP16: {
+			uint16_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
+				*dst++ = clr;
+			break;
+		}
+#endif
+#ifdef CONFIG_VIDEO_BPP32
+		case VIDEO_BPP32: {
+			uint32_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
+				*dst++ = clr;
+			break;
+		}
+#endif
+		default:
+			return -ENOSYS;
+		}
+		line += vid_priv->line_length;
+	}
+
+	return 0;
+}
+
+static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc,
+			       uint count)
+{
+	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+	void *dst;
+	void *src;
+	int pbytes = VNBYTES(vid_priv->bpix);
+	int j;
+
+	dst = vid_priv->fb + vid_priv->line_length -
+		(rowdst + count) * VIDEO_FONT_HEIGHT * pbytes;
+	src = vid_priv->fb + vid_priv->line_length -
+		(rowsrc + count) * VIDEO_FONT_HEIGHT * pbytes;
+
+	for (j = 0; j < vid_priv->ysize; j++) {
+		memmove(dst, src, VIDEO_FONT_HEIGHT * pbytes * count);
+		src += vid_priv->line_length;
+		dst += vid_priv->line_length;
+	}
+
+	return 0;
+}
+
+static int console_putc_xy_1(struct udevice *dev, uint x, uint y, char ch)
+{
+	struct udevice *vid = dev->parent;
+	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
+	int pbytes = VNBYTES(vid_priv->bpix);
+	int i, col;
+	int mask = 0x80;
+	void *line = vid_priv->fb + (x + 1) * vid_priv->line_length -
+		(y + 1) * pbytes;
+	uchar *pfont = video_fontdata + ch * VIDEO_FONT_HEIGHT;
+
+	for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
+		switch (vid_priv->bpix) {
+#ifdef CONFIG_VIDEO_BPP8
+		case VIDEO_BPP8: {
+			uint8_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
+				*dst-- = (pfont[i] & mask) ? vid_priv->colour_fg
+					: vid_priv->colour_bg;
+			}
+			break;
+		}
+#endif
+#ifdef CONFIG_VIDEO_BPP16
+		case VIDEO_BPP16: {
+			uint16_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
+				*dst-- = (pfont[i] & mask) ? vid_priv->colour_fg
+					: vid_priv->colour_bg;
+			}
+			break;
+		}
+#endif
+#ifdef CONFIG_VIDEO_BPP32
+		case VIDEO_BPP32: {
+			uint32_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
+				*dst-- = (pfont[i] & mask) ? vid_priv->colour_fg
+					: vid_priv->colour_bg;
+			}
+			break;
+		}
+#endif
+		default:
+			return -ENOSYS;
+		}
+		line += vid_priv->line_length;
+		mask >>= 1;
+	}
+
+	return 0;
+}
+
+
+static int console_set_row_2(struct udevice *dev, uint row, int clr)
+{
+	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+	void *line;
+	int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize;
+	int i;
+
+	line = vid_priv->fb + vid_priv->ysize * vid_priv->line_length -
+		(row + 1) * VIDEO_FONT_HEIGHT * vid_priv->line_length;
+	switch (vid_priv->bpix) {
+#ifdef CONFIG_VIDEO_BPP8
+	case VIDEO_BPP8: {
+		uint8_t *dst = line;
+
+		for (i = 0; i < pixels; i++)
+			*dst++ = clr;
+		break;
+	}
+#endif
+#ifdef CONFIG_VIDEO_BPP16
+	case VIDEO_BPP16: {
+		uint16_t *dst = line;
+
+		for (i = 0; i < pixels; i++)
+			*dst++ = clr;
+		break;
+	}
+#endif
+#ifdef CONFIG_VIDEO_BPP32
+	case VIDEO_BPP32: {
+		uint32_t *dst = line;
+
+		for (i = 0; i < pixels; i++)
+			*dst++ = clr;
+		break;
+	}
+#endif
+	default:
+		return -ENOSYS;
+	}
+
+	return 0;
+}
+
+static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc,
+			       uint count)
+{
+	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+	void *dst;
+	void *src;
+	void *end;
+
+	end = vid_priv->fb + vid_priv->ysize * vid_priv->line_length;
+	dst = end - (rowdst + count) * VIDEO_FONT_HEIGHT *
+		vid_priv->line_length;
+	src = end - (rowsrc + count) * VIDEO_FONT_HEIGHT *
+		vid_priv->line_length;
+	memmove(dst, src, VIDEO_FONT_HEIGHT * vid_priv->line_length * count);
+
+	return 0;
+}
+
+static int console_putc_xy_2(struct udevice *dev, uint x, uint y, char ch)
+{
+	struct udevice *vid = dev->parent;
+	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
+	int i, row;
+	void *line;
+
+	line = vid_priv->fb + (vid_priv->ysize - y - 1) * vid_priv->line_length +
+		(vid_priv->xsize - x - VIDEO_FONT_WIDTH - 1) *
+		VNBYTES(vid_priv->bpix);
+
+	for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
+		uchar bits = video_fontdata[ch * VIDEO_FONT_HEIGHT + row];
+
+		switch (vid_priv->bpix) {
+#ifdef CONFIG_VIDEO_BPP8
+		case VIDEO_BPP8: {
+			uint8_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
+				*dst-- = (bits & 0x80) ? vid_priv->colour_fg
+					: vid_priv->colour_bg;
+				bits <<= 1;
+			}
+			break;
+		}
+#endif
+#ifdef CONFIG_VIDEO_BPP16
+		case VIDEO_BPP16: {
+			uint16_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
+				*dst-- = (bits & 0x80) ? vid_priv->colour_fg
+					: vid_priv->colour_bg;
+				bits <<= 1;
+			}
+			break;
+		}
+#endif
+#ifdef CONFIG_VIDEO_BPP32
+		case VIDEO_BPP32: {
+			uint32_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
+				*dst-- = (bits & 0x80) ? vid_priv->colour_fg
+					: vid_priv->colour_bg;
+				bits <<= 1;
+			}
+			break;
+		}
+#endif
+		default:
+			return -ENOSYS;
+		}
+		line -= vid_priv->line_length;
+	}
+
+	return 0;
+}
+
+static int console_set_row_3(struct udevice *dev, uint row, int clr)
+{
+	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+	int pbytes = VNBYTES(vid_priv->bpix);
+	void *line;
+	int i, j;
+
+	line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * pbytes;
+	for (j = 0; j < vid_priv->ysize; j++) {
+		switch (vid_priv->bpix) {
+#ifdef CONFIG_VIDEO_BPP8
+		case VIDEO_BPP8: {
+			uint8_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
+				*dst++ = clr;
+			break;
+		}
+#endif
+#ifdef CONFIG_VIDEO_BPP16
+		case VIDEO_BPP16: {
+			uint16_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
+				*dst++ = clr;
+			break;
+		}
+#endif
+#ifdef CONFIG_VIDEO_BPP32
+		case VIDEO_BPP32: {
+			uint32_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
+				*dst++ = clr;
+			break;
+		}
+#endif
+		default:
+			return -ENOSYS;
+		}
+		line += vid_priv->line_length;
+	}
+
+	return 0;
+}
+
+static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc,
+			       uint count)
+{
+	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+	void *dst;
+	void *src;
+	int pbytes = VNBYTES(vid_priv->bpix);
+	int j;
+
+	dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * pbytes;
+	src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * pbytes;
+
+	for (j = 0; j < vid_priv->ysize; j++) {
+		memmove(dst, src, VIDEO_FONT_HEIGHT * pbytes * count);
+		src += vid_priv->line_length;
+		dst += vid_priv->line_length;
+	}
+
+	return 0;
+}
+
+static int console_putc_xy_3(struct udevice *dev, uint x, uint y, char ch)
+{
+	struct udevice *vid = dev->parent;
+	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
+	int pbytes = VNBYTES(vid_priv->bpix);
+	int i, col;
+	int mask = 0x80;
+	void *line = vid_priv->fb + (vid_priv->ysize - x - 1) *
+		vid_priv->line_length + y * pbytes;
+	uchar *pfont = video_fontdata + ch * VIDEO_FONT_HEIGHT;
+
+	for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
+		switch (vid_priv->bpix) {
+#ifdef CONFIG_VIDEO_BPP8
+		case VIDEO_BPP8: {
+			uint8_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
+				*dst++ = (pfont[i] & mask) ? vid_priv->colour_fg
+					: vid_priv->colour_bg;
+			}
+			break;
+		}
+#endif
+#ifdef CONFIG_VIDEO_BPP16
+		case VIDEO_BPP16: {
+			uint16_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
+				*dst++ = (pfont[i] & mask) ? vid_priv->colour_fg
+					: vid_priv->colour_bg;
+			}
+			break;
+		}
+#endif
+#ifdef CONFIG_VIDEO_BPP32
+		case VIDEO_BPP32: {
+			uint32_t *dst = line;
+
+			for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
+				*dst++ = (pfont[i] & mask) ? vid_priv->colour_fg
+					: vid_priv->colour_bg;
+			}
+			break;
+		}
+#endif
+		default:
+			return -ENOSYS;
+		}
+		line -= vid_priv->line_length;
+		mask >>= 1;
+	}
+
+	return 0;
+}
+
+
+static int console_probe_1_3(struct udevice *dev)
+{
+	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
+	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+
+	priv->cols = vid_priv->ysize / VIDEO_FONT_WIDTH;
+	priv->rows = vid_priv->xsize / VIDEO_FONT_HEIGHT;
+
+	return 0;
+}
+
+struct vidconsole_ops console_ops_1 = {
+	.putc_xy	= console_putc_xy_1,
+	.move_rows	= console_move_rows_1,
+	.set_row	= console_set_row_1,
+};
+
+struct vidconsole_ops console_ops_2 = {
+	.putc_xy	= console_putc_xy_2,
+	.move_rows	= console_move_rows_2,
+	.set_row	= console_set_row_2,
+};
+
+struct vidconsole_ops console_ops_3 = {
+	.putc_xy	= console_putc_xy_3,
+	.move_rows	= console_move_rows_3,
+	.set_row	= console_set_row_3,
+};
+
+U_BOOT_DRIVER(vidconsole_1) = {
+	.name	= "vidconsole1",
+	.id	= UCLASS_VIDEO_CONSOLE,
+	.ops	= &console_ops_1,
+	.probe	= console_probe_1_3,
+};
+
+U_BOOT_DRIVER(vidconsole_2) = {
+	.name	= "vidconsole2",
+	.id	= UCLASS_VIDEO_CONSOLE,
+	.ops	= &console_ops_2,
+};
+
+U_BOOT_DRIVER(vidconsole_3) = {
+	.name	= "vidconsole3",
+	.id	= UCLASS_VIDEO_CONSOLE,
+	.ops	= &console_ops_3,
+	.probe	= console_probe_1_3,
+};
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 10/18] common: Move LCD and video memory reservation together
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (8 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 09/18] dm: video: Add a driver for a rotated text console Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-17 23:37   ` Anatolij Gustschin
  2016-01-05 16:31 ` [U-Boot] [PATCH 11/18] dm: common: Add memory reservation for the video uclass Simon Glass
                   ` (8 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

These two functions are conceptually the same. Move them together in the
pre-relocation init.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 common/board_f.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/common/board_f.c b/common/board_f.c
index 8094ac4..068db0d 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -451,22 +451,10 @@ static int reserve_lcd(void)
 }
 #endif /* CONFIG_LCD */
 
-static int reserve_trace(void)
-{
-#ifdef CONFIG_TRACE
-	gd->relocaddr -= CONFIG_TRACE_BUFFER_SIZE;
-	gd->trace_buff = map_sysmem(gd->relocaddr, CONFIG_TRACE_BUFFER_SIZE);
-	debug("Reserving %dk for trace data at: %08lx\n",
-	      CONFIG_TRACE_BUFFER_SIZE >> 10, gd->relocaddr);
-#endif
-
-	return 0;
-}
-
 #if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \
 		!defined(CONFIG_ARM) && !defined(CONFIG_X86) && \
 		!defined(CONFIG_BLACKFIN) && !defined(CONFIG_M68K)
-static int reserve_video(void)
+static int reserve_legacy_video(void)
 {
 	/* reserve memory for video display (always full pages) */
 	gd->relocaddr = video_setmem(gd->relocaddr);
@@ -476,6 +464,18 @@ static int reserve_video(void)
 }
 #endif
 
+static int reserve_trace(void)
+{
+#ifdef CONFIG_TRACE
+	gd->relocaddr -= CONFIG_TRACE_BUFFER_SIZE;
+	gd->trace_buff = map_sysmem(gd->relocaddr, CONFIG_TRACE_BUFFER_SIZE);
+	debug("Reserving %dk for trace data at: %08lx\n",
+	      CONFIG_TRACE_BUFFER_SIZE >> 10, gd->relocaddr);
+#endif
+
+	return 0;
+}
+
 static int reserve_uboot(void)
 {
 	/*
@@ -960,13 +960,13 @@ static init_fnc_t init_sequence_f[] = {
 #ifdef CONFIG_LCD
 	reserve_lcd,
 #endif
-	reserve_trace,
 	/* TODO: Why the dependency on CONFIG_8xx? */
 #if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \
 		!defined(CONFIG_ARM) && !defined(CONFIG_X86) && \
 		!defined(CONFIG_BLACKFIN) && !defined(CONFIG_M68K)
 	reserve_video,
 #endif
+	reserve_trace,
 #if !defined(CONFIG_BLACKFIN)
 	reserve_uboot,
 #endif
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 11/18] dm: common: Add memory reservation for the video uclass
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (9 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 10/18] common: Move LCD and video memory reservation together Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-17 23:39   ` Anatolij Gustschin
  2016-01-05 16:31 ` [U-Boot] [PATCH 12/18] dm: video: Implement the bmp command for driver model Simon Glass
                   ` (7 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

Before relocation we need to reserve memory for the video driver frame
buffers so that they can use this memory when they start up (after
relocation). Add a call to the uclass to permit this.

The current top and bottom of the region is stored in global_data so that
it can be checked post-relocation to ensure enough memory is available. No
video device should be probed before relocation.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 common/board_f.c                  | 47 +++++++++++++++++++++++++++++----------
 include/asm-generic/global_data.h |  4 ++++
 2 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/common/board_f.c b/common/board_f.c
index 068db0d..c470b59 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -46,6 +46,7 @@
 #include <spi.h>
 #include <status_led.h>
 #include <trace.h>
+#include <video.h>
 #include <watchdog.h>
 #include <asm/errno.h>
 #include <asm/io.h>
@@ -437,21 +438,38 @@ static int reserve_mmu(void)
 }
 #endif
 
-#ifdef CONFIG_LCD
+#ifdef CONFIG_DM_VIDEO
+static int reserve_video(void)
+{
+	ulong addr;
+	int ret;
+
+	addr = gd->relocaddr;
+	ret = video_reserve(&addr);
+	if (ret)
+		return ret;
+	gd->relocaddr = addr;
+
+	return 0;
+}
+#else
+
+# ifdef CONFIG_LCD
 static int reserve_lcd(void)
 {
-#ifdef CONFIG_FB_ADDR
+#  ifdef CONFIG_FB_ADDR
 	gd->fb_base = CONFIG_FB_ADDR;
-#else
+#  else
 	/* reserve memory for LCD display (always full pages) */
 	gd->relocaddr = lcd_setmem(gd->relocaddr);
 	gd->fb_base = gd->relocaddr;
-#endif /* CONFIG_FB_ADDR */
+#  endif /* CONFIG_FB_ADDR */
+
 	return 0;
 }
-#endif /* CONFIG_LCD */
+# endif /* CONFIG_LCD */
 
-#if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \
+# if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \
 		!defined(CONFIG_ARM) && !defined(CONFIG_X86) && \
 		!defined(CONFIG_BLACKFIN) && !defined(CONFIG_M68K)
 static int reserve_legacy_video(void)
@@ -462,7 +480,8 @@ static int reserve_legacy_video(void)
 
 	return 0;
 }
-#endif
+# endif
+#endif /* !CONFIG_DM_VIDEO */
 
 static int reserve_trace(void)
 {
@@ -957,15 +976,19 @@ static init_fnc_t init_sequence_f[] = {
 		defined(CONFIG_ARM)
 	reserve_mmu,
 #endif
-#ifdef CONFIG_LCD
+#ifdef CONFIG_DM_VIDEO
+	reserve_video,
+#else
+# ifdef CONFIG_LCD
 	reserve_lcd,
-#endif
+# endif
 	/* TODO: Why the dependency on CONFIG_8xx? */
-#if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \
+# if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \
 		!defined(CONFIG_ARM) && !defined(CONFIG_X86) && \
 		!defined(CONFIG_BLACKFIN) && !defined(CONFIG_M68K)
-	reserve_video,
-#endif
+	reserve_legacy_video,
+# endif
+#endif /* CONFIG_DM_VIDEO */
 	reserve_trace,
 #if !defined(CONFIG_BLACKFIN)
 	reserve_uboot,
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 5d8b043..a587d3c 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -122,6 +122,10 @@ typedef struct global_data {
 	struct membuff console_out;	/* console output */
 	struct membuff console_in;	/* console input */
 #endif
+#ifdef CONFIG_DM_VIDEO
+	ulong video_top;		/* Top of video frame buffer area */
+	ulong video_bottom;		/* Bottom of video frame buffer area */
+#endif
 } gd_t;
 #endif
 
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 12/18] dm: video: Implement the bmp command for driver model
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (10 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 11/18] dm: common: Add memory reservation for the video uclass Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-18  0:01   ` Anatolij Gustschin
  2016-01-05 16:31 ` [U-Boot] [PATCH 13/18] dm: stdio: video: Plumb the video uclass into stdio Simon Glass
                   ` (6 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

This command can use the bitmap display code in the uclass. This is similar
to the code in lcd.c and cfb_console.c. These other copies will go away when
all boards are converted to use driver model for video.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 common/cmd_bmp.c          |  22 ++-
 drivers/video/Makefile    |   1 +
 drivers/video/video_bmp.c | 353 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 375 insertions(+), 1 deletion(-)
 create mode 100644 drivers/video/video_bmp.c

diff --git a/common/cmd_bmp.c b/common/cmd_bmp.c
index f04b7d4..fd5b7db 100644
--- a/common/cmd_bmp.c
+++ b/common/cmd_bmp.c
@@ -10,7 +10,9 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <lcd.h>
+#include <mapmem.h>
 #include <bmp_layout.h>
 #include <command.h>
 #include <asm/byteorder.h>
@@ -225,6 +227,9 @@ static int bmp_info(ulong addr)
  */
 int bmp_display(ulong addr, int x, int y)
 {
+#ifdef CONFIG_DM_VIDEO
+	struct udevice *dev;
+#endif
 	int ret;
 	struct bmp_image *bmp = map_sysmem(addr, 0);
 	void *bmp_alloc_addr = NULL;
@@ -240,7 +245,22 @@ int bmp_display(ulong addr, int x, int y)
 	}
 	addr = map_to_sysmem(bmp);
 
-#if defined(CONFIG_LCD)
+#ifdef CONFIG_DM_VIDEO
+	ret = uclass_first_device(UCLASS_VIDEO, &dev);
+	if (!ret) {
+		if (!dev)
+			ret = -ENODEV;
+		if (!ret) {
+			bool align = false;
+
+# ifdef CONFIG_SPLASH_SCREEN_ALIGN
+			align = true;
+# endif /* CONFIG_SPLASH_SCREEN_ALIGN */
+			ret = video_bmp_display(dev, addr, x, y, align);
+		}
+	}
+	return ret ? CMD_RET_FAILURE : 0;
+#elif defined(CONFIG_LCD)
 	ret = lcd_display_bitmap(addr, x, y);
 #elif defined(CONFIG_VIDEO)
 	ret = video_display_bitmap(addr, x, y);
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 8f26d1d..ee04629 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -8,6 +8,7 @@
 ifdef CONFIG_DM
 obj-$(CONFIG_DISPLAY_PORT) += dp-uclass.o
 obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o console_normal.o
+obj-$(CONFIG_DM_VIDEO) += video_bmp.o
 obj-$(CONFIG_VIDEO_ROTATION) += console_rotate.o
 endif
 
diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c
new file mode 100644
index 0000000..c9075d6
--- /dev/null
+++ b/drivers/video/video_bmp.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <bmp_layout.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <video.h>
+#include <watchdog.h>
+#include <asm/unaligned.h>
+
+#ifdef CONFIG_VIDEO_BMP_RLE8
+#define BMP_RLE8_ESCAPE		0
+#define BMP_RLE8_EOL		0
+#define BMP_RLE8_EOBMP		1
+#define BMP_RLE8_DELTA		2
+
+static void draw_unencoded_bitmap(ushort **fbp, uchar *bmap, ushort *cmap,
+				  int cnt)
+{
+	while (cnt > 0) {
+		*(*fbp)++ = cmap[*bmap++];
+		cnt--;
+	}
+}
+
+static void draw_encoded_bitmap(ushort **fbp, ushort col, int cnt)
+{
+	ushort *fb = *fbp;
+
+	while (cnt > 0) {
+		*fb++ = col;
+		cnt--;
+	}
+	*fbp = fb;
+}
+
+static void video_display_rle8_bitmap(struct udevice *dev,
+				      struct bmp_image *bmp, ushort *cmap,
+				      uchar *fb, int x_off, int y_off)
+{
+	struct video_priv *priv = dev_get_uclass_priv(dev);
+	uchar *bmap;
+	ulong width, height;
+	ulong cnt, runlen;
+	int x, y;
+	int decode = 1;
+
+	debug("%s\n", __func__);
+	width = get_unaligned_le32(&bmp->header.width);
+	height = get_unaligned_le32(&bmp->header.height);
+	bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset);
+
+	x = 0;
+	y = height - 1;
+
+	while (decode) {
+		if (bmap[0] == BMP_RLE8_ESCAPE) {
+			switch (bmap[1]) {
+			case BMP_RLE8_EOL:
+				/* end of line */
+				bmap += 2;
+				x = 0;
+				y--;
+				/* 16bpix, 2-byte per pixel, width should *2 */
+				fb -= (width * 2 + priv->line_length);
+				break;
+			case BMP_RLE8_EOBMP:
+				/* end of bitmap */
+				decode = 0;
+				break;
+			case BMP_RLE8_DELTA:
+				/* delta run */
+				x += bmap[2];
+				y -= bmap[3];
+				/* 16bpix, 2-byte per pixel, x should *2 */
+				fb = (uchar *)(priv->fb + (y + y_off - 1)
+					* priv->line_length + (x + x_off) * 2);
+				bmap += 4;
+				break;
+			default:
+				/* unencoded run */
+				runlen = bmap[1];
+				bmap += 2;
+				if (y < height) {
+					if (x < width) {
+						if (x + runlen > width)
+							cnt = width - x;
+						else
+							cnt = runlen;
+						draw_unencoded_bitmap(
+							(ushort **)&fb,
+							bmap, cmap, cnt);
+					}
+					x += runlen;
+				}
+				bmap += runlen;
+				if (runlen & 1)
+					bmap++;
+			}
+		} else {
+			/* encoded run */
+			if (y < height) {
+				runlen = bmap[0];
+				if (x < width) {
+					/* aggregate the same code */
+					while (bmap[0] == 0xff &&
+					       bmap[2] != BMP_RLE8_ESCAPE &&
+					       bmap[1] == bmap[3]) {
+						runlen += bmap[2];
+						bmap += 2;
+					}
+					if (x + runlen > width)
+						cnt = width - x;
+					else
+						cnt = runlen;
+					draw_encoded_bitmap((ushort **)&fb,
+						cmap[bmap[1]], cnt);
+				}
+				x += runlen;
+			}
+			bmap += 2;
+		}
+	}
+}
+#endif
+
+__weak void fb_put_byte(uchar **fb, uchar **from)
+{
+	*(*fb)++ = *(*from)++;
+}
+
+#if defined(CONFIG_BMP_16BPP)
+__weak void fb_put_word(uchar **fb, uchar **from)
+{
+	*(*fb)++ = *(*from)++;
+	*(*fb)++ = *(*from)++;
+}
+#endif /* CONFIG_BMP_16BPP */
+
+#define BMP_ALIGN_CENTER	0x7fff
+
+/**
+ * video_splash_align_axis() - Align a single coordinate
+ *
+ *- if a coordinate is 0x7fff then the image will be centred in
+ *  that direction
+ *- if a coordinate is -ve then it will be offset to the
+ *  left/top of the centre by that many pixels
+ *- if a coordinate is positive it will be used unchnaged.
+ *
+ * @axis:	Input and output coordinate
+ * @panel_size:	Size of panel in pixels for that axis
+ * @picture_size:	Size of bitmap in pixels for that axis
+ */
+static void video_splash_align_axis(int *axis, unsigned long panel_size,
+				    unsigned long picture_size)
+{
+	unsigned long panel_picture_delta = panel_size - picture_size;
+	unsigned long axis_alignment;
+
+	if (*axis == BMP_ALIGN_CENTER)
+		axis_alignment = panel_picture_delta / 2;
+	else if (*axis < 0)
+		axis_alignment = panel_picture_delta + *axis + 1;
+	else
+		return;
+
+	*axis = max(0, (int)axis_alignment);
+}
+
+static void video_set_cmap(struct udevice *dev,
+			   struct bmp_color_table_entry *cte, unsigned colours)
+{
+	struct video_priv *priv = dev_get_uclass_priv(dev);
+	int i;
+	ushort *cmap = priv->cmap;
+
+	debug("%s: colours=%d\n", __func__, colours);
+	for (i = 0; i < colours; ++i) {
+		*cmap = ((cte->red   << 8) & 0xf800) |
+			((cte->green << 3) & 0x07e0) |
+			((cte->blue  >> 3) & 0x001f);
+		cmap++;
+		cte++;
+	}
+}
+
+int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
+		      bool align)
+{
+	struct video_priv *priv = dev_get_uclass_priv(dev);
+	ushort *cmap_base = NULL;
+	ushort i, j;
+	uchar *fb;
+	struct bmp_image *bmp = map_sysmem(bmp_image, 0);
+	uchar *bmap;
+	ushort padded_width;
+	unsigned long width, height, byte_width;
+	unsigned long pwidth = priv->xsize;
+	unsigned colours, bpix, bmp_bpix;
+	struct bmp_color_table_entry *palette;
+	int hdr_size;
+
+	if (!bmp || !(bmp->header.signature[0] == 'B' &&
+	    bmp->header.signature[1] == 'M')) {
+		printf("Error: no valid bmp image at %lx\n", bmp_image);
+
+		return -EINVAL;
+	}
+
+	width = get_unaligned_le32(&bmp->header.width);
+	height = get_unaligned_le32(&bmp->header.height);
+	bmp_bpix = get_unaligned_le16(&bmp->header.bit_count);
+	hdr_size = get_unaligned_le16(&bmp->header.size);
+	debug("hdr_size=%d, bmp_bpix=%d\n", hdr_size, bmp_bpix);
+	palette = (void *)bmp + 14 + hdr_size;
+
+	colours = 1 << bmp_bpix;
+
+	bpix = VNBITS(priv->bpix);
+
+	if (bpix != 1 && bpix != 8 && bpix != 16 && bpix != 32) {
+		printf("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
+		       bpix, bmp_bpix);
+
+		return -EINVAL;
+	}
+
+	/*
+	 * We support displaying 8bpp BMPs on 16bpp LCDs
+	 * and displaying 24bpp BMPs on 32bpp LCDs
+	 * */
+	if (bpix != bmp_bpix &&
+	    !(bmp_bpix == 8 && bpix == 16) &&
+	    !(bmp_bpix == 24 && bpix == 32)) {
+		printf("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
+		       bpix, get_unaligned_le16(&bmp->header.bit_count));
+		return -EPERM;
+	}
+
+	debug("Display-bmp: %d x %d  with %d colours, display %d\n",
+	      (int)width, (int)height, (int)colours, 1 << bpix);
+
+	if (bmp_bpix == 8)
+		video_set_cmap(dev, palette, colours);
+
+	padded_width = (width & 0x3 ? (width & ~0x3) + 4 : width);
+
+	if (align) {
+		video_splash_align_axis(&x, priv->xsize, width);
+		video_splash_align_axis(&y, priv->ysize, height);
+	}
+
+	if ((x + width) > pwidth)
+		width = pwidth - x;
+	if ((y + height) > priv->ysize)
+		height = priv->ysize - y;
+
+	bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset);
+	fb = (uchar *)(priv->fb +
+		(y + height - 1) * priv->line_length + x * bpix / 8);
+
+	switch (bmp_bpix) {
+	case 1:
+	case 8: {
+		cmap_base = priv->cmap;
+#ifdef CONFIG_VIDEO_BMP_RLE8
+		u32 compression = get_unaligned_le32(&bmp->header.compression);
+		debug("compressed %d %d\n", compression, BMP_BI_RLE8);
+		if (compression == BMP_BI_RLE8) {
+			if (bpix != 16) {
+				/* TODO implement render code for bpix != 16 */
+				printf("Error: only support 16 bpix");
+				return -EPROTONOSUPPORT;
+			}
+			video_display_rle8_bitmap(dev, bmp, cmap_base, fb, x,
+						  y);
+			break;
+		}
+#endif
+
+		if (bpix != 16)
+			byte_width = width;
+		else
+			byte_width = width * 2;
+
+		for (i = 0; i < height; ++i) {
+			WATCHDOG_RESET();
+			for (j = 0; j < width; j++) {
+				if (bpix != 16) {
+					fb_put_byte(&fb, &bmap);
+				} else {
+					*(uint16_t *)fb = cmap_base[*bmap];
+					bmap++;
+					fb += sizeof(uint16_t) / sizeof(*fb);
+				}
+			}
+			bmap += (padded_width - width);
+			fb -= byte_width + priv->line_length;
+		}
+		break;
+	}
+#if defined(CONFIG_BMP_16BPP)
+	case 16:
+		for (i = 0; i < height; ++i) {
+			WATCHDOG_RESET();
+			for (j = 0; j < width; j++)
+				fb_put_word(&fb, &bmap);
+
+			bmap += (padded_width - width) * 2;
+			fb -= width * 2 + lcd_line_length;
+		}
+		break;
+#endif /* CONFIG_BMP_16BPP */
+#if defined(CONFIG_BMP_24BMP)
+	case 24:
+		for (i = 0; i < height; ++i) {
+			for (j = 0; j < width; j++) {
+				*(fb++) = *(bmap++);
+				*(fb++) = *(bmap++);
+				*(fb++) = *(bmap++);
+				*(fb++) = 0;
+			}
+			fb -= lcd_line_length + width * (bpix / 8);
+		}
+		break;
+#endif /* CONFIG_BMP_24BMP */
+#if defined(CONFIG_BMP_32BPP)
+	case 32:
+		for (i = 0; i < height; ++i) {
+			for (j = 0; j < width; j++) {
+				*(fb++) = *(bmap++);
+				*(fb++) = *(bmap++);
+				*(fb++) = *(bmap++);
+				*(fb++) = *(bmap++);
+			}
+			fb -= lcd_line_length + width * (bpix / 8);
+		}
+		break;
+#endif /* CONFIG_BMP_32BPP */
+	default:
+		break;
+	};
+
+	video_sync(dev);
+
+	return 0;
+}
+
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 13/18] dm: stdio: video: Plumb the video uclass into stdio
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (11 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 12/18] dm: video: Implement the bmp command for driver model Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-18  0:04   ` Anatolij Gustschin
  2016-01-05 16:31 ` [U-Boot] [PATCH 14/18] sandbox: Move CONFIG_VIDEO_SANDBOX_SDL to Kconfig Simon Glass
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

Register video drivers with stdio so that they can be used for text output.
This needs to be done explicitly for now. At some point we should be able to
convert stdio itself to driver model and avoid this step.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 common/stdio.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/common/stdio.c b/common/stdio.c
index 8311ac7..7252bab 100644
--- a/common/stdio.c
+++ b/common/stdio.c
@@ -281,12 +281,23 @@ int stdio_add_devices(void)
 	i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
 #endif
 #endif
-#ifdef CONFIG_LCD
+#ifdef CONFIG_DM_VIDEO
+	struct udevice *vdev;
+
+	for (ret = uclass_first_device(UCLASS_VIDEO, &vdev);
+	     vdev;
+	     ret = uclass_next_device(&vdev))
+		;
+	if (ret)
+		printf("%s: Video device failed (ret=%d)\n", __func__, ret);
+#else
+# if defined(CONFIG_LCD)
 	drv_lcd_init ();
-#endif
-#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
+# endif
+# if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
 	drv_video_init ();
-#endif
+# endif
+#endif /* CONFIG_DM_VIDEO */
 #if defined(CONFIG_KEYBOARD) && !defined(CONFIG_DM_KEYBOARD)
 	drv_keyboard_init ();
 #endif
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 14/18] sandbox: Move CONFIG_VIDEO_SANDBOX_SDL to Kconfig
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (12 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 13/18] dm: stdio: video: Plumb the video uclass into stdio Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-18  0:05   ` Anatolij Gustschin
  2016-01-05 16:31 ` [U-Boot] [PATCH 15/18] dm: video: sandbox: Convert sandbox to use driver model for video Simon Glass
                   ` (4 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

Move this option to Kconfig. This is quite simple as only sandbox uses the
driver.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 configs/sandbox_defconfig | 3 ++-
 drivers/video/Kconfig     | 9 +++++++++
 include/configs/sandbox.h | 1 -
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 731fc25..e4b8412 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -1,6 +1,7 @@
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_PCI=y
 CONFIG_DEFAULT_DEVICE_TREE="sandbox"
+CONFIG_DM_PCI_COMPAT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_FIT_SIGNATURE=y
@@ -51,7 +52,6 @@ CONFIG_SPI_FLASH_SST=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_DM_ETH=y
 CONFIG_DM_PCI=y
-CONFIG_DM_PCI_COMPAT=y
 CONFIG_PCI_SANDBOX=y
 CONFIG_PINCTRL=y
 CONFIG_PINCONF=y
@@ -76,6 +76,7 @@ CONFIG_USB_EMUL=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL=y
+CONFIG_VIDEO_SANDBOX_SDL=y
 CONFIG_SYS_VSNPRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_TPM=y
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 39df24e..b90850b 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -300,6 +300,15 @@ config DISPLAY_PORT
 	   to drive LCD panels. This framework provides support for enabling
 	   these displays where supported by the video hardware.
 
+config VIDEO_SANDBOX_SDL
+	bool "Enable sandbox video console using SDL"
+	depends on SANDBOX
+	help
+	  When using sandbox you can enable an emulated LCD display which
+	  appears as an SDL (Simple DirectMedia Layer) window. This is a
+	  console device and can display stdout output. Within U-Boot is is
+	  a normal bitmap display and can display images as well as text.
+
 config VIDEO_TEGRA124
 	bool "Enable video support on Tegra124"
 	help
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index d3112e1..e1be603 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -159,7 +159,6 @@
 /* LCD and keyboard require SDL support */
 #ifdef CONFIG_SANDBOX_SDL
 #define CONFIG_LCD
-#define CONFIG_VIDEO_SANDBOX_SDL
 #define CONFIG_CMD_BMP
 #define CONFIG_BOARD_EARLY_INIT_F
 #define CONFIG_CONSOLE_MUX
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 15/18] dm: video: sandbox: Convert sandbox to use driver model for video
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (13 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 14/18] sandbox: Move CONFIG_VIDEO_SANDBOX_SDL to Kconfig Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-18  0:10   ` Anatolij Gustschin
  2016-01-05 16:31 ` [U-Boot] [PATCH 16/18] dm: video: test: Add tests for the video uclass Simon Glass
                   ` (3 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

Now that driver model support is available, convert sandbox over to use it.
We can remove a few of the special hooks that sandbox currently has.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/sandbox/dts/sandbox.dts |  1 +
 board/sandbox/sandbox.c      | 17 --------
 common/lcd.c                 | 11 -----
 configs/sandbox_defconfig    |  1 +
 drivers/serial/sandbox.c     |  5 +--
 drivers/video/sandbox_sdl.c  | 95 ++++++++++++++++++++++----------------------
 include/configs/sandbox.h    | 10 ++---
 include/fdtdec.h             |  1 -
 lib/fdtdec.c                 |  1 -
 9 files changed, 56 insertions(+), 86 deletions(-)

diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index d2addb4..e3f02bf 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -117,6 +117,7 @@
 	};
 
 	lcd {
+		u-boot,dm-pre-reloc;
 		compatible = "sandbox,lcd-sdl";
 		xres = <1366>;
 		yres = <768>;
diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c
index 592f772..b41e9de 100644
--- a/board/sandbox/sandbox.c
+++ b/board/sandbox/sandbox.c
@@ -47,23 +47,6 @@ int dram_init(void)
 	return 0;
 }
 
-#ifdef CONFIG_BOARD_EARLY_INIT_F
-int board_early_init_f(void)
-{
-#ifdef CONFIG_VIDEO_SANDBOX_SDL
-	int ret;
-
-	ret = sandbox_lcd_sdl_early_init();
-	if (ret) {
-		puts("Could not init sandbox LCD emulation\n");
-		return ret;
-	}
-#endif
-
-	return 0;
-}
-#endif
-
 #ifdef CONFIG_BOARD_LATE_INIT
 int board_late_init(void)
 {
diff --git a/common/lcd.c b/common/lcd.c
index d29308a..2f3594a 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -31,10 +31,6 @@
 #endif
 #endif
 
-#ifdef CONFIG_SANDBOX
-#include <asm/sdl.h>
-#endif
-
 #ifndef CONFIG_LCD_ALIGNMENT
 #define CONFIG_LCD_ALIGNMENT PAGE_SIZE
 #endif
@@ -72,13 +68,6 @@ void lcd_sync(void)
 	if (lcd_flush_dcache)
 		flush_dcache_range((u32)lcd_base,
 			(u32)(lcd_base + lcd_get_size(&line_length)));
-#elif defined(CONFIG_SANDBOX) && defined(CONFIG_VIDEO_SANDBOX_SDL)
-	static ulong last_sync;
-
-	if (get_timer(last_sync) > 10) {
-		sandbox_sdl_sync(lcd_base);
-		last_sync = get_timer(0);
-	}
 #endif
 }
 
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index e4b8412..3b6017f 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -76,6 +76,7 @@ CONFIG_USB_EMUL=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL=y
+CONFIG_DM_VIDEO=y
 CONFIG_VIDEO_SANDBOX_SDL=y
 CONFIG_SYS_VSNPRINTF=y
 CONFIG_CMD_DHRYSTONE=y
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c
index cd2f91e..45dff98 100644
--- a/drivers/serial/sandbox.c
+++ b/drivers/serial/sandbox.c
@@ -16,6 +16,7 @@
 #include <lcd.h>
 #include <os.h>
 #include <serial.h>
+#include <video.h>
 #include <linux/compiler.h>
 #include <asm/state.h>
 
@@ -114,9 +115,7 @@ static int sandbox_serial_pending(struct udevice *dev, bool input)
 		return 0;
 
 	os_usleep(100);
-#ifdef CONFIG_LCD
-	lcd_sync();
-#endif
+	video_sync_all();
 	if (next_index == serial_buf_read)
 		return 1;	/* buffer full */
 
diff --git a/drivers/video/sandbox_sdl.c b/drivers/video/sandbox_sdl.c
index ba4578e..450628e 100644
--- a/drivers/video/sandbox_sdl.c
+++ b/drivers/video/sandbox_sdl.c
@@ -5,75 +5,76 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <fdtdec.h>
-#include <lcd.h>
-#include <malloc.h>
+#include <video.h>
 #include <asm/sdl.h>
 #include <asm/u-boot-sandbox.h>
+#include <dm/test.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
 enum {
-	/* Maximum LCD size we support */
+	/* Default LCD size we support */
 	LCD_MAX_WIDTH		= 1366,
 	LCD_MAX_HEIGHT		= 768,
-	LCD_MAX_LOG2_BPP	= 4,		/* 2^4 = 16 bpp */
 };
 
-vidinfo_t panel_info;
 
-void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
-{
-}
+/* This platform data is needed in tests, so declare it here */
+struct sandbox_sdl_plat {
+	int xres;
+	int yres;
+	int bpix;
+	int rot;
+};
 
-void lcd_ctrl_init(void *lcdbase)
+static int sandbox_sdl_probe(struct udevice *dev)
 {
-	/*
-	 * Allocate memory to keep BMP color conversion map. This is required
-	 * for 8 bit BMPs only (hence 256 colors). If malloc fails - keep
-	 * going, it is not even clear if displyaing the bitmap will be
-	 * required on the way up.
-	 */
-	panel_info.cmap = malloc(256 * NBITS(panel_info.vl_bpix) / 8);
-}
+	struct sandbox_sdl_plat *plat = dev_get_platdata(dev);
+	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+	int ret;
 
-void lcd_enable(void)
-{
-	if (sandbox_sdl_init_display(panel_info.vl_col, panel_info.vl_row,
-				     panel_info.vl_bpix))
+	ret = sandbox_sdl_init_display(plat->xres, plat->yres, plat->bpix);
+	if (ret) {
 		puts("LCD init failed\n");
+		return ret;
+	}
+	uc_priv->xsize = plat->xres;
+	uc_priv->ysize = plat->yres;
+	uc_priv->bpix = plat->bpix;
+	uc_priv->rot = plat->rot;
+
+	return 0;
 }
 
-int sandbox_lcd_sdl_early_init(void)
+static int sandbox_sdl_bind(struct udevice *dev)
 {
+	struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
+	struct sandbox_sdl_plat *plat = dev_get_platdata(dev);
 	const void *blob = gd->fdt_blob;
-	int xres = LCD_MAX_WIDTH, yres = LCD_MAX_HEIGHT;
-	int node;
+	int node = dev->of_offset;
 	int ret = 0;
 
-	/*
-	 * The code in common/lcd.c does not cope with not being able to
-	 * set up a frame buffer. It will just happily keep writing to
-	 * invalid memory. So here we make sure that at least some buffer
-	 * is available even if it actually won't be displayed.
-	 */
-	node = fdtdec_next_compatible(blob, 0, COMPAT_SANDBOX_LCD_SDL);
-	if (node >= 0) {
-		xres = fdtdec_get_int(blob, node, "xres", LCD_MAX_WIDTH);
-		yres = fdtdec_get_int(blob, node, "yres", LCD_MAX_HEIGHT);
-		if (xres < 0 || xres > LCD_MAX_WIDTH) {
-			xres = LCD_MAX_WIDTH;
-			ret = -EINVAL;
-		}
-		if (yres < 0 || yres > LCD_MAX_HEIGHT) {
-			yres = LCD_MAX_HEIGHT;
-			ret = -EINVAL;
-		}
-	}
-
-	panel_info.vl_col = xres;
-	panel_info.vl_row = yres;
-	panel_info.vl_bpix = LCD_COLOR16;
+	plat->xres = fdtdec_get_int(blob, node, "xres", LCD_MAX_WIDTH);
+	plat->yres = fdtdec_get_int(blob, node, "yres", LCD_MAX_HEIGHT);
+	plat->bpix = VIDEO_BPP16;
+	uc_plat->size = plat->xres * plat->yres * (1 << plat->bpix) / 8;
+	debug("%s: Frame buffer size %x\n", __func__, uc_plat->size);
 
 	return ret;
 }
+
+static const struct udevice_id sandbox_sdl_ids[] = {
+	{ .compatible = "sandbox,lcd-sdl" },
+	{ }
+};
+
+U_BOOT_DRIVER(sdl_sandbox) = {
+	.name	= "sdl_sandbox",
+	.id	= UCLASS_VIDEO,
+	.of_match = sandbox_sdl_ids,
+	.bind	= sandbox_sdl_bind,
+	.probe	= sandbox_sdl_probe,
+	.platdata_auto_alloc_size	= sizeof(struct sandbox_sdl_plat),
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index e1be603..23ae44c 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -158,9 +158,7 @@
 
 /* LCD and keyboard require SDL support */
 #ifdef CONFIG_SANDBOX_SDL
-#define CONFIG_LCD
 #define CONFIG_CMD_BMP
-#define CONFIG_BOARD_EARLY_INIT_F
 #define CONFIG_CONSOLE_MUX
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
 #define LCD_BPP			LCD_COLOR16
@@ -169,12 +167,12 @@
 #define CONFIG_KEYBOARD
 
 #define SANDBOX_SERIAL_SETTINGS		"stdin=serial,cros-ec-keyb,usbkbd\0" \
-					"stdout=serial,lcd\0" \
-					"stderr=serial,lcd\0"
+					"stdout=serial,lcd.vidconsole\0" \
+					"stderr=serial,lcd.vidconsole\0"
 #else
 #define SANDBOX_SERIAL_SETTINGS		"stdin=serial\0" \
-					"stdout=serial,lcd\0" \
-					"stderr=serial,lcd\0"
+					"stdout=serial,lcd.vidconsole\0" \
+					"stderr=serial,lcd.vidconsole\0"
 #endif
 
 #define SANDBOX_ETH_SETTINGS		"ethaddr=00:00:11:22:33:44\0" \
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 018d151..954036e 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -151,7 +151,6 @@ enum fdt_compat_id {
 	COMPAT_GENERIC_SPI_FLASH,	/* Generic SPI Flash chip */
 	COMPAT_MAXIM_98095_CODEC,	/* MAX98095 Codec */
 	COMPAT_SAMSUNG_EXYNOS5_I2C,	/* Exynos5 High Speed I2C Controller */
-	COMPAT_SANDBOX_LCD_SDL,		/* Sandbox LCD emulation with SDL */
 	COMPAT_SAMSUNG_EXYNOS_SYSMMU,	/* Exynos sysmmu */
 	COMPAT_INTEL_MICROCODE,		/* Intel microcode update */
 	COMPAT_MEMORY_SPD,		/* Memory SPD information */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index f6f23ae..a0e7be7 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -56,7 +56,6 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(GENERIC_SPI_FLASH, "spi-flash"),
 	COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"),
 	COMPAT(SAMSUNG_EXYNOS5_I2C, "samsung,exynos5-hsi2c"),
-	COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"),
 	COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
 	COMPAT(INTEL_MICROCODE, "intel,microcode"),
 	COMPAT(MEMORY_SPD, "memory-spd"),
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 16/18] dm: video: test: Add tests for the video uclass
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (14 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 15/18] dm: video: sandbox: Convert sandbox to use driver model for video Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-18  0:18   ` Anatolij Gustschin
  2016-01-05 16:31 ` [U-Boot] [PATCH 17/18] dm: video: test: Add tests for rotated consoles Simon Glass
                   ` (2 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

Add tests that check that the video console is working correcty. Also check
that text output produces the expected result. Test coverage includes
character output, wrapping and scrolling.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/sandbox/dts/test.dts   |   7 ++
 drivers/video/sandbox_sdl.c |   9 ---
 include/dm/test.h           |   8 ++
 test/dm/Makefile            |   1 +
 test/dm/video.c             | 190 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 206 insertions(+), 9 deletions(-)
 create mode 100644 test/dm/video.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 2e0d320..9b8d658 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -195,6 +195,13 @@
 		vss-microvolts = <0>;
 	};
 
+	lcd {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,lcd-sdl";
+		xres = <1366>;
+		yres = <768>;
+	};
+
 	leds {
 		compatible = "gpio-leds";
 
diff --git a/drivers/video/sandbox_sdl.c b/drivers/video/sandbox_sdl.c
index 450628e..21448a1 100644
--- a/drivers/video/sandbox_sdl.c
+++ b/drivers/video/sandbox_sdl.c
@@ -20,15 +20,6 @@ enum {
 	LCD_MAX_HEIGHT		= 768,
 };
 
-
-/* This platform data is needed in tests, so declare it here */
-struct sandbox_sdl_plat {
-	int xres;
-	int yres;
-	int bpix;
-	int rot;
-};
-
 static int sandbox_sdl_probe(struct udevice *dev)
 {
 	struct sandbox_sdl_plat *plat = dev_get_platdata(dev);
diff --git a/include/dm/test.h b/include/dm/test.h
index a4bc5c8..ca924d9 100644
--- a/include/dm/test.h
+++ b/include/dm/test.h
@@ -155,6 +155,14 @@ enum {
 /* Declare a new driver model test */
 #define DM_TEST(_name, _flags)	UNIT_TEST(_name, _flags, dm_test)
 
+/* This platform data is needed in tests, so declare it here */
+struct sandbox_sdl_plat {
+	int xres;
+	int yres;
+	int bpix;
+	int rot;
+};
+
 /* Declare ping methods for the drivers */
 int test_ping(struct udevice *dev, int pingval, int *pingret);
 int testfdt_ping(struct udevice *dev, int pingval, int *pingret);
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 681c6ae..fd0198f 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -34,5 +34,6 @@ obj-$(CONFIG_DM_USB) += usb.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_REGULATOR) += regulator.o
 obj-$(CONFIG_TIMER) += timer.o
+obj-$(CONFIG_DM_VIDEO) += video.o
 obj-$(CONFIG_ADC) += adc.o
 endif
diff --git a/test/dm/video.c b/test/dm/video.c
new file mode 100644
index 0000000..5867a4f
--- /dev/null
+++ b/test/dm/video.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <bzlib.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <os.h>
+#include <video.h>
+#include <video_console.h>
+#include <dm/test.h>
+#include <dm/uclass-internal.h>
+#include <test/ut.h>
+
+/*
+ * These tests use the standard sandbox frame buffer, the resolutino of which
+ * is defined in the device tree. This only supports 16bpp so the tests only
+ * test that code path. It would be possible to adjust this fairly easily,
+ * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
+ * in sandbox_sdl_sync() would also need to change to handle the different
+ * surface depth.
+ */
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Basic test of the video uclass */
+static int dm_test_video_base(struct unit_test_state *uts)
+{
+	struct video_priv *priv;
+	struct udevice *dev;
+
+	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
+	ut_asserteq(1366, video_get_xsize(dev));
+	ut_asserteq(768, video_get_ysize(dev));
+	priv = dev_get_uclass_priv(dev);
+	ut_asserteq(priv->fb_size, 1366 * 768 * 2);
+
+	return 0;
+}
+DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/**
+ * compress_frame_buffer() - Compress the frame buffer and return its size
+ *
+ * We want to write tests which perform operations on the video console and
+ * check that the frame buffer ends up with the correct contents. But it is
+ * painful to store 'known good' images for comparison with the frame
+ * buffer. As an alternative, we can compress the frame buffer and check the
+ * size of the compressed data. This provides a pretty good level of
+ * certainty and the resulting tests need only check a single value.
+ *
+ * @dev:	Video device
+ * @return compressed size of the frame buffer, or -ve on error
+ */
+static int compress_frame_buffer(struct udevice *dev)
+{
+	struct video_priv *priv = dev_get_uclass_priv(dev);
+	uint destlen;
+	void *dest;
+	int ret;
+
+	destlen = priv->fb_size;
+	dest = malloc(priv->fb_size);
+	if (!dest)
+		return -ENOMEM;
+	ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
+				       priv->fb, priv->fb_size,
+				       3, 0, 0);
+	free(dest);
+	if (ret)
+		return ret;
+
+	return destlen;
+}
+
+/*
+ * Call this function at any point to halt and show the current display. Be
+ * sure to run the test with the -l flag.
+ */
+static void __maybe_unused see_output(void)
+{
+	video_sync_all();
+	while (1);
+}
+
+/* Test text output works on the video console */
+static int dm_test_video_text(struct unit_test_state *uts)
+{
+	struct udevice *dev, *con;
+	int i;
+
+#define WHITE		0xffff
+#define SCROLL_LINES	100
+
+	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
+	ut_asserteq(46, compress_frame_buffer(dev));
+
+	ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
+	vidconsole_putc_xy(con, 0, 0, 'a');
+	ut_asserteq(79, compress_frame_buffer(dev));
+
+	vidconsole_putc_xy(con, 0, 0, ' ');
+	ut_asserteq(46, compress_frame_buffer(dev));
+
+	for (i = 0; i < 20; i++)
+		vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
+	ut_asserteq(273, compress_frame_buffer(dev));
+
+	vidconsole_set_row(con, 0, WHITE);
+	ut_asserteq(46, compress_frame_buffer(dev));
+
+	for (i = 0; i < 20; i++)
+		vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
+	ut_asserteq(273, compress_frame_buffer(dev));
+
+	return 0;
+}
+DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test handling of special characters in the console */
+static int dm_test_video_chars(struct unit_test_state *uts)
+{
+	struct udevice *dev, *con;
+	const char *test_string = "Well\b\b\b\bxhe is\r \n\ta very modest  \bman\n\t\tand Has much to\b\bto be modest about.";
+	const char *s;
+
+	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
+	ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
+	for (s = test_string; *s; s++)
+		vidconsole_put_char(con, *s);
+	ut_asserteq(466, compress_frame_buffer(dev));
+
+	return 0;
+}
+DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/**
+ * check_vidconsole_output() - Run a text console test
+ *
+ * @uts:	Test state
+ * @rot:	Console rotation (0, 90, 180, 270)
+ * @wrap_size:	Expected size of compressed frame buffer for the wrap test
+ * @scroll_size: Same for the scroll test
+ * @return 0 on success
+ */
+static int check_vidconsole_output(struct unit_test_state *uts, int rot,
+				   int wrap_size, int scroll_size)
+{
+	struct udevice *dev, *con;
+	struct sandbox_sdl_plat *plat;
+	int i;
+
+	ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
+	ut_assert(!device_active(dev));
+	plat = dev_get_platdata(dev);
+	plat->rot = rot;
+
+	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
+	ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
+	ut_asserteq(46, compress_frame_buffer(dev));
+
+	/* Check display wrap */
+	for (i = 0; i < 120; i++)
+		vidconsole_put_char(con, 'A' + i % 50);
+	ut_asserteq(wrap_size, compress_frame_buffer(dev));
+
+	/* Check display scrolling */
+	for (i = 0; i < SCROLL_LINES; i++) {
+		vidconsole_put_char(con, 'A' + i % 50);
+		vidconsole_put_char(con, '\n');
+	}
+	ut_asserteq(scroll_size, compress_frame_buffer(dev));
+
+	/* If we scroll enough, the screen becomes blank again */
+	for (i = 0; i < SCROLL_LINES; i++)
+		vidconsole_put_char(con, '\n');
+	ut_asserteq(46, compress_frame_buffer(dev));
+
+	return 0;
+}
+
+/* Test text output through the console uclass */
+static int dm_test_video_context(struct unit_test_state *uts)
+{
+	return check_vidconsole_output(uts, 0, 788, 453);
+}
+DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 17/18] dm: video: test: Add tests for rotated consoles
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (15 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 16/18] dm: video: test: Add tests for the video uclass Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-18  0:20   ` Anatolij Gustschin
  2016-01-05 16:31 ` [U-Boot] [PATCH 18/18] dm: video: test: Test that bitmap display works correctly Simon Glass
  2016-01-13 17:58 ` [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Hannes Schmelzer
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

Test that text is displayed correctly when the console is rotated.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 configs/sandbox_defconfig |  1 +
 test/dm/video.c           | 27 +++++++++++++++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 3b6017f..b55d5e5 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -77,6 +77,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL=y
 CONFIG_DM_VIDEO=y
+CONFIG_VIDEO_ROTATION=y
 CONFIG_VIDEO_SANDBOX_SDL=y
 CONFIG_SYS_VSNPRINTF=y
 CONFIG_CMD_DHRYSTONE=y
diff --git a/test/dm/video.c b/test/dm/video.c
index 5867a4f..a5332fa 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -188,3 +188,30 @@ static int dm_test_video_context(struct unit_test_state *uts)
 	return check_vidconsole_output(uts, 0, 788, 453);
 }
 DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test rotated text output through the console uclass */
+static int dm_test_video_rotation1(struct unit_test_state *uts)
+{
+	ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
+
+	return 0;
+}
+DM_TEST(dm_test_video_rotation1, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test rotated text output through the console uclass */
+static int dm_test_video_rotation2(struct unit_test_state *uts)
+{
+	ut_assertok(check_vidconsole_output(uts, 2, 785, 446));
+
+	return 0;
+}
+DM_TEST(dm_test_video_rotation2, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test rotated text output through the console uclass */
+static int dm_test_video_rotation3(struct unit_test_state *uts)
+{
+	ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
+
+	return 0;
+}
+DM_TEST(dm_test_video_rotation3, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 18/18] dm: video: test: Test that bitmap display works correctly
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (16 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 17/18] dm: video: test: Add tests for rotated consoles Simon Glass
@ 2016-01-05 16:31 ` Simon Glass
  2016-01-18  0:26   ` Anatolij Gustschin
  2016-01-13 17:58 ` [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Hannes Schmelzer
  18 siblings, 1 reply; 44+ messages in thread
From: Simon Glass @ 2016-01-05 16:31 UTC (permalink / raw)
  To: u-boot

Add a test for the 'bmp' command. Test both the uncompressed and compressed
versions of the file, since they use different code paths.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 include/configs/sandbox.h |   2 ++
 test/dm/video.c           |  54 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/logos/denx-comp.bmp | Bin 0 -> 4148 bytes
 3 files changed, 56 insertions(+)
 create mode 100644 tools/logos/denx-comp.bmp

diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 23ae44c..6498981 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -163,6 +163,8 @@
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
 #define LCD_BPP			LCD_COLOR16
 #define CONFIG_LCD_BMP_RLE8
+#define CONFIG_VIDEO_BMP_RLE8
+#define CONFIG_SPLASH_SCREEN_ALIGN
 
 #define CONFIG_KEYBOARD
 
diff --git a/test/dm/video.c b/test/dm/video.c
index a5332fa..52aba2e 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -215,3 +215,57 @@ static int dm_test_video_rotation3(struct unit_test_state *uts)
 	return 0;
 }
 DM_TEST(dm_test_video_rotation3, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Read a file into memory and return a pointer to it */
+static int read_file(struct unit_test_state *uts, const char *fname,
+		     ulong *addrp)
+{
+	int buf_size = 100000;
+	ulong addr = 0;
+	int size, fd;
+	char *buf;
+
+	buf = map_sysmem(addr, 0);
+	ut_assert(buf != NULL);
+	fd = os_open(fname, OS_O_RDONLY);
+	ut_assert(fd >= 0);
+	size = os_read(fd, buf, buf_size);
+	ut_assert(size >= 0);
+	ut_assert(size < buf_size);
+	os_close(fd);
+	*addrp = addr;
+
+	return 0;
+}
+
+/* Test drawing a bitmap file */
+static int dm_test_video_bmp(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	ulong addr;
+
+	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
+	ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
+
+	ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
+	ut_asserteq(1368, compress_frame_buffer(dev));
+
+	return 0;
+}
+DM_TEST(dm_test_video_bmp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test drawing a compressed bitmap file */
+static int dm_test_video_bmp_comp(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	ulong addr;
+
+	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
+	ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
+
+	ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
+	ut_asserteq(1368, compress_frame_buffer(dev));
+
+	return 0;
+}
+DM_TEST(dm_test_video_bmp_comp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
diff --git a/tools/logos/denx-comp.bmp b/tools/logos/denx-comp.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..89d0f471c85cf734b5f0e2bb2508d39f5b9e72b8
GIT binary patch
literal 4148
zcmeH}JBVCW7{|ZwzF%|i?CfTD_HOoU9!9h=1``B36Gbe<AYvs!EaD?*V<8b+Q&?(h
zNm>O{DjKjbg$6`yOp(GSK^vPDZ4|D*@7%dFJBwIaNQOOg&pqGkfBxTN_VhC+$KpTl
zM<VaCyTW>jrIN8kJ}yPxm at R)`htdsy{^j&j&%I?E`#k at -`>WrHoIihlzQ6JN0~jqn
zgj at QYdis={dEtzlefg}Md-I%Jc;|v#ymV16eQ-%Ge{@-{esWc=eRfT*e|=qUet%PL
z-M%Gvf4(cbzwOE+Uv%>LSDie2qmviE>E!kAI(hqtPTu>mlMioqa^<H^KE2b)m%nuK
z?XR8O+U?}dAD!&}*-6(e!CJy}@8uo?_ZawZ7&z)eQPqg=^fjjm&q%{i0w;3B1(LE}
zaayQoo;Wl`y+mtvNrLoMmObq}a*1eVHnGEx<c?`p*n8&B0#3AwMMIt;&%|Vf)0DaA
zzs(c7Ff~+o40zXk<gLx4`Dwh4#pwNxdVG;-?e~>BEe!{g)#(V#agEl14zzi`$D5%s
zxvl-43?GQ2u=fRGtroue`*EhW8*bbC<23pwk6<$|S%ii0Z3uJEc#jXcv7GY;|I2=J
zI80oxtto8I8H88-S>z!r#$nX^3R3cI at dkvwSE2+I!R#E}O7UP(dtagDZ5DxiRH0|p
zvZsmZ_<IzVFC;ZA<>psiY%J!PM>Cvgg|EaU=*9hM2-d+rSlF99rv<Ly^CZ5WpeB$M
zNBj5mNp$XGZ}PxJ@V>%HBrE8$qk<dWdk)6zsOwCT)jjgkv<;_tY*bKe9QCy|<~f0<
z*m@(i%)yBD#oQX-k*}h9u<s+8u36(9UdUdc#z at xR$=lm`WswFXR?R85AVy5Q5m-b^
z`0()te^w!!=ax&qE3vQXQ|`FmQ{OXSfM2VD0Tn#Z3n3@Qggw{1R7<<Jv2B)<9(w{F
z!>SAG84r2S)au+;M<C#)Rx9R112BRfmJ-{AGII2DTJT+YO)c>ba<j0mCAUl+tE|~w
zU>+VaPEupqD(fNijN5a5?<=l0?(F@z`ACBj?_jnQtBYZ+63f`MIj6;gun?rwc6r?C
zmac1i%xSCZVmuZjv<{Jpk?eTP;B1pdx3`>bCXE>Wa6*1sdX;BzaITd#I^J+OI;A^+
zmnk>pS+{eIqR|#CTLn7wfKIvZ8ojnDn{%D2S#cHe%pJ5$gj+J5%SMeJgq7_P^3*xl
zAU-}e<{C8-N~hx*jl}K1D|brJ$roN4ZbS6#2A$Z|)Cd)tYhX9$b~Ps at IV?3{#^iHk
z+b}h$o7 at p&q8nDP71c_AM<uM3SeMq(S%2SxTcoU*JVdTQ3i7)2Q?-C;Dm~fqxJy@p
zh#9g1KWhp4q3Ks+`>u1ot($tDN3OtQ(PU_Wk!h*b1dWV!+<U8$Vh>K!$mIab=2R{Z
z&*a=5jl3!58s>+7%lNGt^;%T!Bty$`YI;nhI+G3f&d|)|g!eVZi?T|uk&`Kt;-wzs
zx`GGuvc1qbMx`F{_A4e~Ro*_M3iip`y)x$AvgPWMH2YWSlC6$Ya=2t2ne}0^PM<Ox
z!L`S`j;0<N@@OvKgH3}$o>8-V at 5Ha6+z%rsSY&a=hTS*tJRO5e`h+?=;2B=o!>DD?
z<QvqAWsz#%!uOP15L-8g{AocCA+=n`Of=J6WSC5of1Bnu$=EAhRj1%&&-_?a3tbR!
z7LDzH7@H(@VKECIxyqSli`w%Q&3_W)I<?xj`RBj$!sZqou4^%MJ)7%vh(>e-eNtHm
zlnpbYM03$2v1{xXCe?V%IX#%tf%Xd=F+=)&sS!O|@|(M at o4Pvd#Z_&s*AHX$7=55E
z{XL<-C)VGoJ7n0BM{VA;bnbMR4jI#dD$h?Do|eh7HB1&Xvu(1)bV@*wPQj|}FqaIy
zO{R4^9mbM%n}}`Mta4jF9jlfcFd1`j1`~_k=1o5ri5D?5GRyrsQP>Aq=iDlT>0!=J
xZO)RVl5uUE)G_*-_8u``QZKPxq!rV&4Qw8@)aGW0-441JsjvUhv$Xq&{tYdt;;8 at t

literal 0
HcmV?d00001

-- 
2.6.0.rc2.230.g3dd15c0

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

* [U-Boot] [PATCH 01/18] tiny-printf: Always print zeroes
  2016-01-05 16:30 ` [U-Boot] [PATCH 01/18] tiny-printf: Always print zeroes Simon Glass
@ 2016-01-05 17:08   ` Stefan Roese
  2016-01-13 21:55   ` Tom Rini
  1 sibling, 0 replies; 44+ messages in thread
From: Stefan Roese @ 2016-01-05 17:08 UTC (permalink / raw)
  To: u-boot

On 05.01.2016 17:30, Simon Glass wrote:
> At present this does not print zero values in numeric format (hex and
> decimal). Add a special case for this.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   lib/tiny-printf.c | 16 ++++++++++++----
>   1 file changed, 12 insertions(+), 4 deletions(-)
>
> diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c
> index efe5c25..a06abed 100644
> --- a/lib/tiny-printf.c
> +++ b/lib/tiny-printf.c
> @@ -82,13 +82,21 @@ int vprintf(const char *fmt, va_list va)
>   					num = -(int)num;
>   					out('-');
>   				}
> -				for (div = 1000000000; div; div /= 10)
> -					div_out(&num, div);
> +				if (!num) {
> +					out_dgt(0);
> +				} else {
> +					for (div = 1000000000; div; div /= 10)
> +						div_out(&num, div);
> +				}
>   				break;
>   			case 'x':
>   				num = va_arg(va, unsigned int);
> -				for (div = 0x10000000; div; div /= 0x10)
> -					div_out(&num, div);
> +				if (!num) {
> +					out_dgt(0);
> +				} else {
> +					for (div = 0x10000000; div; div /= 0x10)
> +						div_out(&num, div);
> +				}
>   				break;
>   			case 'c':
>   				out((char)(va_arg(va, int)));
>

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

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

* [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support
  2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
                   ` (17 preceding siblings ...)
  2016-01-05 16:31 ` [U-Boot] [PATCH 18/18] dm: video: test: Test that bitmap display works correctly Simon Glass
@ 2016-01-13 17:58 ` Hannes Schmelzer
  2016-01-13 20:10   ` Simon Glass
  18 siblings, 1 reply; 44+ messages in thread
From: Hannes Schmelzer @ 2016-01-13 17:58 UTC (permalink / raw)
  To: u-boot

Hi Simon,
> This series starts the process of converting LCD and video devices over to
> use driver model. Both now use a very similar API thanks to earlier work by
> Nikita Kiryanov. With the driver-model conversion these will end up unified
> in a single uclass.
>
> Unfortunately there are different features supported by each. This
> implementation provides for a common set of features which should serve
> most purposes. The intent is to support:
>
> - bitmap devices with 8, 16 and 32 bits per pixel
> - text console wih white on black or vice versa
> - rotated text console
> - bitmap display (BMP format)
>
> More can be added as additional boards are ported over to use driver model
> for video.
>
> The name 'video' is chosen for the uclass since it is more generic than LCD.
> Another option would be 'display' but that would introduce a third concept
> to U-Boot which seems like the wrong approach.
This is very welcome ... i will patch my tree with your changes and try 
to adapt my LCD-driver (am335xfb.c) to new driver-model and run some 
tests on the B&R boards.
> The existing LCD and video init functions are not needed now, so this uclass
> does not implement them. This includes lcd_ctrl_init(), lcd_enable() and
> video_init().
This is not true for me, i use this functions to setup lcd-timings and 
backlight switch on.
You can have a look at the B&R tseries board.
Maybe we can consider how to setup an lcd device (different timing, 
backlights) in future,
> Tests are provided to check that console text and bitmap output is correct.
> These should be able to be extended as more features are added.
>
> Future work will convert a few boards over to use driver model for video.
> Likely targets are x86, exynos, tegra. Also, Rockchip LCD support will be
> added using driver model (patches will likely be sent some time in January).
best regards,
Hannes

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

* [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support
  2016-01-13 17:58 ` [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Hannes Schmelzer
@ 2016-01-13 20:10   ` Simon Glass
  0 siblings, 0 replies; 44+ messages in thread
From: Simon Glass @ 2016-01-13 20:10 UTC (permalink / raw)
  To: u-boot

Hi Hannes,

On 13 January 2016 at 10:58, Hannes Schmelzer <hannes@schmelzer.or.at> wrote:
> Hi Simon,
>>
>> This series starts the process of converting LCD and video devices over to
>> use driver model. Both now use a very similar API thanks to earlier work
>> by
>> Nikita Kiryanov. With the driver-model conversion these will end up
>> unified
>> in a single uclass.
>>
>> Unfortunately there are different features supported by each. This
>> implementation provides for a common set of features which should serve
>> most purposes. The intent is to support:
>>
>> - bitmap devices with 8, 16 and 32 bits per pixel
>> - text console wih white on black or vice versa
>> - rotated text console
>> - bitmap display (BMP format)
>>
>> More can be added as additional boards are ported over to use driver model
>> for video.
>>
>> The name 'video' is chosen for the uclass since it is more generic than
>> LCD.
>> Another option would be 'display' but that would introduce a third concept
>> to U-Boot which seems like the wrong approach.
>
> This is very welcome ... i will patch my tree with your changes and try to
> adapt my LCD-driver (am335xfb.c) to new driver-model and run some tests on
> the B&R boards.

OK. I have some further work to get out in the next week or so. In the
meantime you can check out u-boot-dm/rkh-working. But I'll update it
by tomorrow as there are some changes.

>>
>> The existing LCD and video init functions are not needed now, so this
>> uclass
>> does not implement them. This includes lcd_ctrl_init(), lcd_enable() and
>> video_init().
>
> This is not true for me, i use this functions to setup lcd-timings and
> backlight switch on.
> You can have a look at the B&R tseries board.
> Maybe we can consider how to setup an lcd device (different timing,
> backlights) in future,

Yes I have the same issue with most boards. This is handled by new
uclasses I have added. Have been a bit slow due to Christmas, etc. but
will get this stuff out next week.

>>
>> Tests are provided to check that console text and bitmap output is
>> correct.
>> These should be able to be extended as more features are added.
>>
>> Future work will convert a few boards over to use driver model for video.
>> Likely targets are x86, exynos, tegra. Also, Rockchip LCD support will be
>> added using driver model (patches will likely be sent some time in
>> January).
>
> best regards,
> Hannes

Regards,
Simon

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

* [U-Boot] [PATCH 01/18] tiny-printf: Always print zeroes
  2016-01-05 16:30 ` [U-Boot] [PATCH 01/18] tiny-printf: Always print zeroes Simon Glass
  2016-01-05 17:08   ` Stefan Roese
@ 2016-01-13 21:55   ` Tom Rini
  2016-01-16  1:26     ` Simon Glass
  1 sibling, 1 reply; 44+ messages in thread
From: Tom Rini @ 2016-01-13 21:55 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 05, 2016 at 09:30:57AM -0700, Simon Glass wrote:

> At present this does not print zero values in numeric format (hex and
> decimal). Add a special case for this.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/5188c298/attachment.sig>

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

* [U-Boot] [PATCH 02/18] sandbox: Support the bmp command
  2016-01-05 16:30 ` [U-Boot] [PATCH 02/18] sandbox: Support the bmp command Simon Glass
@ 2016-01-13 21:55   ` Tom Rini
  2016-01-16  1:26     ` Simon Glass
  0 siblings, 1 reply; 44+ messages in thread
From: Tom Rini @ 2016-01-13 21:55 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 05, 2016 at 09:30:58AM -0700, Simon Glass wrote:

> Adjust this command to use map_sysmem() correctly so that it works on
> sandbox.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/2f8dbc49/attachment.sig>

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

* [U-Boot] [PATCH 03/18] dm: core: Call uclass post_bind() after the driver's bind() method
  2016-01-05 16:30 ` [U-Boot] [PATCH 03/18] dm: core: Call uclass post_bind() after the driver's bind() method Simon Glass
@ 2016-01-13 21:55   ` Tom Rini
  2016-01-16  1:26     ` Simon Glass
  0 siblings, 1 reply; 44+ messages in thread
From: Tom Rini @ 2016-01-13 21:55 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 05, 2016 at 09:30:59AM -0700, Simon Glass wrote:

> At present the uclass's post_bind() method is called before the driver's
> bind() method. This means that the uclass cannot use any of the information
> set up by the driver. Move it later in the sequence to permit this.
> 
> This is an ordering change which is always fairly major in nature. The main
> impact is that devices which have children will not see them appear in their
> bind() method. From what I can see, existing drivers do not look at their
> children in the bind() method, so this should be safe.
> 
> Conceptually this change seems to result in a 'more correct' ordering, since
> the uclass (which is broader than the device) gets the last word.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/c401634c/attachment.sig>

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

* [U-Boot] [PATCH 04/18] bzip2: Support compression for sandbox
  2016-01-05 16:31 ` [U-Boot] [PATCH 04/18] bzip2: Support compression for sandbox Simon Glass
@ 2016-01-13 21:55   ` Tom Rini
  2016-01-16  1:26     ` Simon Glass
  0 siblings, 1 reply; 44+ messages in thread
From: Tom Rini @ 2016-01-13 21:55 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 05, 2016 at 09:31:00AM -0700, Simon Glass wrote:

> Add the missing code to allow bzip2 compression to be used. This is useful
> for sandbox tests. These files are taken from the bzip2 1.0.6 release.
> The license text is copied to the top of each file as is done with other
> bzip2 files in U-Boot. The only other change is to squash a compiler warning
> with nBytes.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/700cf2d1/attachment.sig>

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

* [U-Boot] [PATCH 01/18] tiny-printf: Always print zeroes
  2016-01-13 21:55   ` Tom Rini
@ 2016-01-16  1:26     ` Simon Glass
  0 siblings, 0 replies; 44+ messages in thread
From: Simon Glass @ 2016-01-16  1:26 UTC (permalink / raw)
  To: u-boot

On 13 January 2016 at 14:55, Tom Rini <trini@konsulko.com> wrote:
> On Tue, Jan 05, 2016 at 09:30:57AM -0700, Simon Glass wrote:
>
>> At present this does not print zero values in numeric format (hex and
>> decimal). Add a special case for this.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>
> Reviewed-by: Tom Rini <trini@konsulko.com>
>
> --
> Tom

Applied to u-boot-dm

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

* [U-Boot] [PATCH 02/18] sandbox: Support the bmp command
  2016-01-13 21:55   ` Tom Rini
@ 2016-01-16  1:26     ` Simon Glass
  0 siblings, 0 replies; 44+ messages in thread
From: Simon Glass @ 2016-01-16  1:26 UTC (permalink / raw)
  To: u-boot

On 13 January 2016 at 14:55, Tom Rini <trini@konsulko.com> wrote:
> On Tue, Jan 05, 2016 at 09:30:58AM -0700, Simon Glass wrote:
>
>> Adjust this command to use map_sysmem() correctly so that it works on
>> sandbox.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>
> Reviewed-by: Tom Rini <trini@konsulko.com>
>
> --
> Tom

Applied to u-boot-dm

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

* [U-Boot] [PATCH 03/18] dm: core: Call uclass post_bind() after the driver's bind() method
  2016-01-13 21:55   ` Tom Rini
@ 2016-01-16  1:26     ` Simon Glass
  0 siblings, 0 replies; 44+ messages in thread
From: Simon Glass @ 2016-01-16  1:26 UTC (permalink / raw)
  To: u-boot

On 13 January 2016 at 14:55, Tom Rini <trini@konsulko.com> wrote:
> On Tue, Jan 05, 2016 at 09:30:59AM -0700, Simon Glass wrote:
>
>> At present the uclass's post_bind() method is called before the driver's
>> bind() method. This means that the uclass cannot use any of the information
>> set up by the driver. Move it later in the sequence to permit this.
>>
>> This is an ordering change which is always fairly major in nature. The main
>> impact is that devices which have children will not see them appear in their
>> bind() method. From what I can see, existing drivers do not look at their
>> children in the bind() method, so this should be safe.
>>
>> Conceptually this change seems to result in a 'more correct' ordering, since
>> the uclass (which is broader than the device) gets the last word.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>
> Reviewed-by: Tom Rini <trini@konsulko.com>
>
> --
> Tom

Applied to u-boot-dm

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

* [U-Boot] [PATCH 04/18] bzip2: Support compression for sandbox
  2016-01-13 21:55   ` Tom Rini
@ 2016-01-16  1:26     ` Simon Glass
  0 siblings, 0 replies; 44+ messages in thread
From: Simon Glass @ 2016-01-16  1:26 UTC (permalink / raw)
  To: u-boot

On 13 January 2016 at 14:55, Tom Rini <trini@konsulko.com> wrote:
> On Tue, Jan 05, 2016 at 09:31:00AM -0700, Simon Glass wrote:
>
>> Add the missing code to allow bzip2 compression to be used. This is useful
>> for sandbox tests. These files are taken from the bzip2 1.0.6 release.
>> The license text is copied to the top of each file as is done with other
>> bzip2 files in U-Boot. The only other change is to squash a compiler warning
>> with nBytes.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>
> Reviewed-by: Tom Rini <trini@konsulko.com>
>
> --
> Tom

Applied to u-boot-dm

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

* [U-Boot] [PATCH 05/18] dm: video: Add a video uclass
  2016-01-05 16:31 ` [U-Boot] [PATCH 05/18] dm: video: Add a video uclass Simon Glass
@ 2016-01-17 18:35   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-17 18:35 UTC (permalink / raw)
  To: u-boot

Hi Simon,

Some minor comments below. Otherwise

Acked-by: Anatolij Gustschin <agust@denx.de>


On Tue,  5 Jan 2016 09:31:01 -0700
Simon Glass <sjg@chromium.org> wrote:
...
> +config VIDEO_BPP8
> +	bool "Support 8-bit-per-pixel displays"
> +	depends on DM_VIDEO
> +	default y if DM_VIDEO
> +	help
> +	  Support drawing text and bitmaps onto a 8-bit-per-pixel display.
> +	  Ebabling this will include code to support this display. Without

s/Ebabling/Enabling/


> +config VIDEO_BPP16
> +	bool "Support 16-bit-per-pixel displays"
> +	depends on DM_VIDEO
> +	default y if DM_VIDEO
> +	help
> +	  Support drawing text and bitmaps onto a 16-bit-per-pixel display.
> +	  Ebabling this will include code to support this display. Without

same typo here.

> +config VIDEO_BPP32
> +	bool "Support 32-bit-per-pixel displays"
> +	depends on DM_VIDEO
> +	default y if DM_VIDEO
> +	help
> +	  Support drawing text and bitmaps onto a 32-bit-per-pixel display.
> +	  Ebabling this will include code to support this display. Without

s/Ebabling/Enabling/

...
> +/**
> + * struct video_priv - Device information used by the video uclass
> + *
> + * @xsize:	Number of pixel columns (e.g. 1366)
> + * @ysize:	Number of pixels rows (e.g.. 768)
> + * @tor:	Display rotation (0=none, 1=90 degrees clockwise, etc.)
> + * @bpix:	Encoded bits per pixel
> + * @fb:		Frame buffer
> + * @fb_size:	Frame buffer size
> + * @fb_size:	Frame buffer size

Please remove duplicated line here.

...
> +/**
> + * video_get_xsize() - Get the height of the display in pixels

s/_xsize/_ysize/

Thanks,

Anatolij

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

* [U-Boot] [PATCH 06/18] dm: lcd: Avoid using the lcd.h header file with driver model
  2016-01-05 16:31 ` [U-Boot] [PATCH 06/18] dm: lcd: Avoid using the lcd.h header file with driver model Simon Glass
@ 2016-01-17 18:40   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-17 18:40 UTC (permalink / raw)
  To: u-boot

On Tue,  5 Jan 2016 09:31:02 -0700
Simon Glass <sjg@chromium.org> wrote:

> The LCD functions and definitions are not used with the driver model video
> uclass. When all boards are converted over we can remove the file. For now,
> use #ifdef to omit the contents.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  common/Makefile |  2 ++
>  include/lcd.h   | 12 ++++++++----
>  2 files changed, 10 insertions(+), 4 deletions(-)

Acked-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

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

* [U-Boot] [PATCH 07/18] dm: video: Add a uclass for the text console
  2016-01-05 16:31 ` [U-Boot] [PATCH 07/18] dm: video: Add a uclass for the text console Simon Glass
@ 2016-01-17 19:09   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-17 19:09 UTC (permalink / raw)
  To: u-boot

On Tue,  5 Jan 2016 09:31:03 -0700
Simon Glass <sjg@chromium.org> wrote:
...
> +/**
> + * vidconsole_put_char() - Output a character to the current console position
> + *
> + * Outputs a character to the console and advances the cursor. This function
> + * handles wrapping to new lines and scrolling the console. Special
> + * characters are handled also: \n, \r, \n and \t.

there are two "\n", one of them should be "\b" it seems.

> + *
> + * The device always starts withthe cursor at position 0,0 (top left). It

s/withthe/with the/

Otherwise

Acked-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

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

* [U-Boot] [PATCH 08/18] dm: video: Add a 'normal' text console driver
  2016-01-05 16:31 ` [U-Boot] [PATCH 08/18] dm: video: Add a 'normal' text console driver Simon Glass
@ 2016-01-17 20:04   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-17 20:04 UTC (permalink / raw)
  To: u-boot

On Tue,  5 Jan 2016 09:31:04 -0700
Simon Glass <sjg@chromium.org> wrote:

> Most of the time we don't need to rotate the display so a simple font
> blitting feature is enough for our purposes. Add a simple driver which
> supports this function. It provides text output on the console using
> the standard 8x16-pixel font.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  drivers/video/Makefile         |   2 +-
>  drivers/video/console_normal.c | 141 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 142 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/video/console_normal.c

Acked-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

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

* [U-Boot] [PATCH 09/18] dm: video: Add a driver for a rotated text console
  2016-01-05 16:31 ` [U-Boot] [PATCH 09/18] dm: video: Add a driver for a rotated text console Simon Glass
@ 2016-01-17 20:07   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-17 20:07 UTC (permalink / raw)
  To: u-boot

On Tue,  5 Jan 2016 09:31:05 -0700
Simon Glass <sjg@chromium.org> wrote:

> Sometimes the console must be rotated. Add a driver which supports rotating
> the text clockwise to 90, 180 and 270 degrees. This can support devices
> where the display is rotated for mechanical reasons.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  drivers/video/Kconfig          |  13 ++
>  drivers/video/Makefile         |   1 +
>  drivers/video/console_rotate.c | 435 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 449 insertions(+)
>  create mode 100644 drivers/video/console_rotate.c

Acked-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

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

* [U-Boot] [PATCH 10/18] common: Move LCD and video memory reservation together
  2016-01-05 16:31 ` [U-Boot] [PATCH 10/18] common: Move LCD and video memory reservation together Simon Glass
@ 2016-01-17 23:37   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-17 23:37 UTC (permalink / raw)
  To: u-boot

On Tue,  5 Jan 2016 09:31:06 -0700
Simon Glass <sjg@chromium.org> wrote:

> These two functions are conceptually the same. Move them together in the
> pre-relocation init.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  common/board_f.c | 28 ++++++++++++++--------------
>  1 file changed, 14 insertions(+), 14 deletions(-)

Acked-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

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

* [U-Boot] [PATCH 11/18] dm: common: Add memory reservation for the video uclass
  2016-01-05 16:31 ` [U-Boot] [PATCH 11/18] dm: common: Add memory reservation for the video uclass Simon Glass
@ 2016-01-17 23:39   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-17 23:39 UTC (permalink / raw)
  To: u-boot

On Tue,  5 Jan 2016 09:31:07 -0700
Simon Glass <sjg@chromium.org> wrote:

> Before relocation we need to reserve memory for the video driver frame
> buffers so that they can use this memory when they start up (after
> relocation). Add a call to the uclass to permit this.
> 
> The current top and bottom of the region is stored in global_data so that
> it can be checked post-relocation to ensure enough memory is available. No
> video device should be probed before relocation.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  common/board_f.c                  | 47 +++++++++++++++++++++++++++++----------
>  include/asm-generic/global_data.h |  4 ++++
>  2 files changed, 39 insertions(+), 12 deletions(-)

Acked-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

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

* [U-Boot] [PATCH 12/18] dm: video: Implement the bmp command for driver model
  2016-01-05 16:31 ` [U-Boot] [PATCH 12/18] dm: video: Implement the bmp command for driver model Simon Glass
@ 2016-01-18  0:01   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-18  0:01 UTC (permalink / raw)
  To: u-boot

On Tue,  5 Jan 2016 09:31:08 -0700
Simon Glass <sjg@chromium.org> wrote:

> This command can use the bitmap display code in the uclass. This is similar
> to the code in lcd.c and cfb_console.c. These other copies will go away when
> all boards are converted to use driver model for video.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  common/cmd_bmp.c          |  22 ++-
>  drivers/video/Makefile    |   1 +
>  drivers/video/video_bmp.c | 353 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 375 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/video/video_bmp.c

Acked-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

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

* [U-Boot] [PATCH 13/18] dm: stdio: video: Plumb the video uclass into stdio
  2016-01-05 16:31 ` [U-Boot] [PATCH 13/18] dm: stdio: video: Plumb the video uclass into stdio Simon Glass
@ 2016-01-18  0:04   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-18  0:04 UTC (permalink / raw)
  To: u-boot

On Tue,  5 Jan 2016 09:31:09 -0700
Simon Glass <sjg@chromium.org> wrote:

> Register video drivers with stdio so that they can be used for text output.
> This needs to be done explicitly for now. At some point we should be able to
> convert stdio itself to driver model and avoid this step.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  common/stdio.c | 19 +++++++++++++++----
>  1 file changed, 15 insertions(+), 4 deletions(-)

Acked-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

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

* [U-Boot] [PATCH 14/18] sandbox: Move CONFIG_VIDEO_SANDBOX_SDL to Kconfig
  2016-01-05 16:31 ` [U-Boot] [PATCH 14/18] sandbox: Move CONFIG_VIDEO_SANDBOX_SDL to Kconfig Simon Glass
@ 2016-01-18  0:05   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-18  0:05 UTC (permalink / raw)
  To: u-boot

On Tue,  5 Jan 2016 09:31:10 -0700
Simon Glass <sjg@chromium.org> wrote:

> Move this option to Kconfig. This is quite simple as only sandbox uses the
> driver.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  configs/sandbox_defconfig | 3 ++-
>  drivers/video/Kconfig     | 9 +++++++++
>  include/configs/sandbox.h | 1 -
>  3 files changed, 11 insertions(+), 2 deletions(-)

Acked-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

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

* [U-Boot] [PATCH 15/18] dm: video: sandbox: Convert sandbox to use driver model for video
  2016-01-05 16:31 ` [U-Boot] [PATCH 15/18] dm: video: sandbox: Convert sandbox to use driver model for video Simon Glass
@ 2016-01-18  0:10   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-18  0:10 UTC (permalink / raw)
  To: u-boot

On Tue,  5 Jan 2016 09:31:11 -0700
Simon Glass <sjg@chromium.org> wrote:

> Now that driver model support is available, convert sandbox over to use it.
> We can remove a few of the special hooks that sandbox currently has.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  arch/sandbox/dts/sandbox.dts |  1 +
>  board/sandbox/sandbox.c      | 17 --------
>  common/lcd.c                 | 11 -----
>  configs/sandbox_defconfig    |  1 +
>  drivers/serial/sandbox.c     |  5 +--
>  drivers/video/sandbox_sdl.c  | 95 ++++++++++++++++++++++----------------------
>  include/configs/sandbox.h    | 10 ++---
>  include/fdtdec.h             |  1 -
>  lib/fdtdec.c                 |  1 -
>  9 files changed, 56 insertions(+), 86 deletions(-)

Acked-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

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

* [U-Boot] [PATCH 16/18] dm: video: test: Add tests for the video uclass
  2016-01-05 16:31 ` [U-Boot] [PATCH 16/18] dm: video: test: Add tests for the video uclass Simon Glass
@ 2016-01-18  0:18   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-18  0:18 UTC (permalink / raw)
  To: u-boot

On Tue,  5 Jan 2016 09:31:12 -0700
Simon Glass <sjg@chromium.org> wrote:

> Add tests that check that the video console is working correcty. Also check
> that text output produces the expected result. Test coverage includes
> character output, wrapping and scrolling.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  arch/sandbox/dts/test.dts   |   7 ++
>  drivers/video/sandbox_sdl.c |   9 ---
>  include/dm/test.h           |   8 ++
>  test/dm/Makefile            |   1 +
>  test/dm/video.c             | 190 ++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 206 insertions(+), 9 deletions(-)
>  create mode 100644 test/dm/video.c
...
> +/*
> + * These tests use the standard sandbox frame buffer, the resolutino of which

s/resolutino/resolution/

Otherwise

Acked-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

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

* [U-Boot] [PATCH 17/18] dm: video: test: Add tests for rotated consoles
  2016-01-05 16:31 ` [U-Boot] [PATCH 17/18] dm: video: test: Add tests for rotated consoles Simon Glass
@ 2016-01-18  0:20   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-18  0:20 UTC (permalink / raw)
  To: u-boot

On Tue,  5 Jan 2016 09:31:13 -0700
Simon Glass <sjg@chromium.org> wrote:

> Test that text is displayed correctly when the console is rotated.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  configs/sandbox_defconfig |  1 +
>  test/dm/video.c           | 27 +++++++++++++++++++++++++++
>  2 files changed, 28 insertions(+)

Acked-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

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

* [U-Boot] [PATCH 18/18] dm: video: test: Test that bitmap display works correctly
  2016-01-05 16:31 ` [U-Boot] [PATCH 18/18] dm: video: test: Test that bitmap display works correctly Simon Glass
@ 2016-01-18  0:26   ` Anatolij Gustschin
  0 siblings, 0 replies; 44+ messages in thread
From: Anatolij Gustschin @ 2016-01-18  0:26 UTC (permalink / raw)
  To: u-boot

On Tue,  5 Jan 2016 09:31:14 -0700
Simon Glass <sjg@chromium.org> wrote:

> Add a test for the 'bmp' command. Test both the uncompressed and compressed
> versions of the file, since they use different code paths.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  include/configs/sandbox.h |   2 ++
>  test/dm/video.c           |  54 ++++++++++++++++++++++++++++++++++++++++++++++
>  tools/logos/denx-comp.bmp | Bin 0 -> 4148 bytes
>  3 files changed, 56 insertions(+)
>  create mode 100644 tools/logos/denx-comp.bmp

Acked-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

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

end of thread, other threads:[~2016-01-18  0:26 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-05 16:30 [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Simon Glass
2016-01-05 16:30 ` [U-Boot] [PATCH 01/18] tiny-printf: Always print zeroes Simon Glass
2016-01-05 17:08   ` Stefan Roese
2016-01-13 21:55   ` Tom Rini
2016-01-16  1:26     ` Simon Glass
2016-01-05 16:30 ` [U-Boot] [PATCH 02/18] sandbox: Support the bmp command Simon Glass
2016-01-13 21:55   ` Tom Rini
2016-01-16  1:26     ` Simon Glass
2016-01-05 16:30 ` [U-Boot] [PATCH 03/18] dm: core: Call uclass post_bind() after the driver's bind() method Simon Glass
2016-01-13 21:55   ` Tom Rini
2016-01-16  1:26     ` Simon Glass
2016-01-05 16:31 ` [U-Boot] [PATCH 04/18] bzip2: Support compression for sandbox Simon Glass
2016-01-13 21:55   ` Tom Rini
2016-01-16  1:26     ` Simon Glass
2016-01-05 16:31 ` [U-Boot] [PATCH 05/18] dm: video: Add a video uclass Simon Glass
2016-01-17 18:35   ` Anatolij Gustschin
2016-01-05 16:31 ` [U-Boot] [PATCH 06/18] dm: lcd: Avoid using the lcd.h header file with driver model Simon Glass
2016-01-17 18:40   ` Anatolij Gustschin
2016-01-05 16:31 ` [U-Boot] [PATCH 07/18] dm: video: Add a uclass for the text console Simon Glass
2016-01-17 19:09   ` Anatolij Gustschin
2016-01-05 16:31 ` [U-Boot] [PATCH 08/18] dm: video: Add a 'normal' text console driver Simon Glass
2016-01-17 20:04   ` Anatolij Gustschin
2016-01-05 16:31 ` [U-Boot] [PATCH 09/18] dm: video: Add a driver for a rotated text console Simon Glass
2016-01-17 20:07   ` Anatolij Gustschin
2016-01-05 16:31 ` [U-Boot] [PATCH 10/18] common: Move LCD and video memory reservation together Simon Glass
2016-01-17 23:37   ` Anatolij Gustschin
2016-01-05 16:31 ` [U-Boot] [PATCH 11/18] dm: common: Add memory reservation for the video uclass Simon Glass
2016-01-17 23:39   ` Anatolij Gustschin
2016-01-05 16:31 ` [U-Boot] [PATCH 12/18] dm: video: Implement the bmp command for driver model Simon Glass
2016-01-18  0:01   ` Anatolij Gustschin
2016-01-05 16:31 ` [U-Boot] [PATCH 13/18] dm: stdio: video: Plumb the video uclass into stdio Simon Glass
2016-01-18  0:04   ` Anatolij Gustschin
2016-01-05 16:31 ` [U-Boot] [PATCH 14/18] sandbox: Move CONFIG_VIDEO_SANDBOX_SDL to Kconfig Simon Glass
2016-01-18  0:05   ` Anatolij Gustschin
2016-01-05 16:31 ` [U-Boot] [PATCH 15/18] dm: video: sandbox: Convert sandbox to use driver model for video Simon Glass
2016-01-18  0:10   ` Anatolij Gustschin
2016-01-05 16:31 ` [U-Boot] [PATCH 16/18] dm: video: test: Add tests for the video uclass Simon Glass
2016-01-18  0:18   ` Anatolij Gustschin
2016-01-05 16:31 ` [U-Boot] [PATCH 17/18] dm: video: test: Add tests for rotated consoles Simon Glass
2016-01-18  0:20   ` Anatolij Gustschin
2016-01-05 16:31 ` [U-Boot] [PATCH 18/18] dm: video: test: Test that bitmap display works correctly Simon Glass
2016-01-18  0:26   ` Anatolij Gustschin
2016-01-13 17:58 ` [U-Boot] [PATCH 00/18] dm: video: Introduce initial driver-model video support Hannes Schmelzer
2016-01-13 20:10   ` Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.