Add sandbox driver and tests for the new OSD uclass. Signed-off-by: Mario Six <mario.six@gdsys.cc> Reviewed-by: Simon Glass <sjg@chromium.org>lime2-spi
parent
9671f696e5
commit
4eea531859
@ -0,0 +1,161 @@ |
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2018 |
||||||
|
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc |
||||||
|
*/ |
||||||
|
#include <common.h> |
||||||
|
#include <display.h> |
||||||
|
#include <dm.h> |
||||||
|
#include <video_osd.h> |
||||||
|
|
||||||
|
#include "sandbox_osd.h" |
||||||
|
|
||||||
|
struct sandbox_osd_priv { |
||||||
|
uint width; |
||||||
|
uint height; |
||||||
|
u16 *buf; |
||||||
|
}; |
||||||
|
|
||||||
|
static const struct udevice_id sandbox_osd_ids[] = { |
||||||
|
{ .compatible = "sandbox,sandbox_osd" }, |
||||||
|
{ } |
||||||
|
}; |
||||||
|
|
||||||
|
inline u16 make_memval(u8 chr, u8 color) |
||||||
|
{ |
||||||
|
return chr * 0x100 + color; |
||||||
|
} |
||||||
|
|
||||||
|
int sandbox_osd_get_info(struct udevice *dev, struct video_osd_info *info) |
||||||
|
{ |
||||||
|
struct sandbox_osd_priv *priv = dev_get_priv(dev); |
||||||
|
|
||||||
|
info->width = priv->width; |
||||||
|
info->height = priv->height; |
||||||
|
info->major_version = 1; |
||||||
|
info->minor_version = 0; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int sandbox_osd_set_mem(struct udevice *dev, uint col, uint row, u8 *buf, |
||||||
|
size_t buflen, uint count) |
||||||
|
{ |
||||||
|
struct sandbox_osd_priv *priv = dev_get_priv(dev); |
||||||
|
int pos; |
||||||
|
u8 *mem = (u8 *)priv->buf; |
||||||
|
int i; |
||||||
|
|
||||||
|
pos = 2 * (row * priv->width + col); |
||||||
|
|
||||||
|
if (pos >= 2 * (priv->width * priv->height)) |
||||||
|
return -EINVAL; |
||||||
|
|
||||||
|
for (i = 0; i < count; i++) |
||||||
|
memcpy(mem + pos + (i * buflen), buf, buflen); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int _sandbox_osd_set_size(struct udevice *dev, uint col, uint row) |
||||||
|
{ |
||||||
|
struct sandbox_osd_priv *priv = dev_get_priv(dev); |
||||||
|
int i; |
||||||
|
uint size; |
||||||
|
|
||||||
|
priv->width = col; |
||||||
|
priv->height = row; |
||||||
|
size = priv->width * priv->height; |
||||||
|
if (!priv->buf) |
||||||
|
priv->buf = calloc(size, sizeof(u16)); |
||||||
|
else |
||||||
|
priv->buf = realloc(priv->buf, size * sizeof(u16)); |
||||||
|
|
||||||
|
if (!priv->buf) |
||||||
|
return -ENOMEM; |
||||||
|
|
||||||
|
/* Fill OSD with black spaces */ |
||||||
|
for (i = 0; i < size; i++) |
||||||
|
priv->buf[i] = make_memval(' ', 'k'); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int sandbox_osd_set_size(struct udevice *dev, uint col, uint row) |
||||||
|
{ |
||||||
|
return _sandbox_osd_set_size(dev, col, row); |
||||||
|
} |
||||||
|
|
||||||
|
int sandbox_osd_print(struct udevice *dev, uint col, uint row, ulong color, |
||||||
|
char *text) |
||||||
|
{ |
||||||
|
struct sandbox_osd_priv *priv = dev_get_priv(dev); |
||||||
|
char cval; |
||||||
|
char *p; |
||||||
|
int pos; |
||||||
|
|
||||||
|
if (col >= priv->width || row >= priv->height) |
||||||
|
return -EINVAL; |
||||||
|
|
||||||
|
switch (color) { |
||||||
|
case COLOR_BLACK: |
||||||
|
cval = 'k'; |
||||||
|
break; |
||||||
|
case COLOR_WHITE: |
||||||
|
cval = 'w'; |
||||||
|
break; |
||||||
|
case COLOR_RED: |
||||||
|
cval = 'r'; |
||||||
|
break; |
||||||
|
case COLOR_GREEN: |
||||||
|
cval = 'g'; |
||||||
|
break; |
||||||
|
case COLOR_BLUE: |
||||||
|
cval = 'b'; |
||||||
|
break; |
||||||
|
default: |
||||||
|
return -EINVAL; |
||||||
|
} |
||||||
|
|
||||||
|
p = text; |
||||||
|
pos = row * priv->width + col; |
||||||
|
|
||||||
|
while (*p) |
||||||
|
priv->buf[pos++] = make_memval(*(p++), cval); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int sandbox_osd_get_mem(struct udevice *dev, u8 *buf, size_t buflen) |
||||||
|
{ |
||||||
|
struct sandbox_osd_priv *priv = dev_get_priv(dev); |
||||||
|
uint memsize = 2 * (priv->width * priv->height); |
||||||
|
|
||||||
|
if (buflen < memsize) |
||||||
|
return -EINVAL; |
||||||
|
|
||||||
|
memcpy(buf, priv->buf, memsize); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static const struct video_osd_ops sandbox_osd_ops = { |
||||||
|
.get_info = sandbox_osd_get_info, |
||||||
|
.set_mem = sandbox_osd_set_mem, |
||||||
|
.set_size = sandbox_osd_set_size, |
||||||
|
.print = sandbox_osd_print, |
||||||
|
}; |
||||||
|
|
||||||
|
int sandbox_osd_probe(struct udevice *dev) |
||||||
|
{ |
||||||
|
return _sandbox_osd_set_size(dev, 10, 10); |
||||||
|
} |
||||||
|
|
||||||
|
U_BOOT_DRIVER(sandbox_osd_drv) = { |
||||||
|
.name = "sandbox_osd_drv", |
||||||
|
.id = UCLASS_VIDEO_OSD, |
||||||
|
.ops = &sandbox_osd_ops, |
||||||
|
.of_match = sandbox_osd_ids, |
||||||
|
.probe = sandbox_osd_probe, |
||||||
|
.priv_auto_alloc_size = sizeof(struct sandbox_osd_priv), |
||||||
|
}; |
@ -0,0 +1,13 @@ |
|||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */ |
||||||
|
/*
|
||||||
|
* (C) Copyright 2018 |
||||||
|
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc |
||||||
|
*/ |
||||||
|
|
||||||
|
enum { |
||||||
|
COLOR_BLACK, |
||||||
|
COLOR_WHITE, |
||||||
|
COLOR_RED, |
||||||
|
COLOR_GREEN, |
||||||
|
COLOR_BLUE, |
||||||
|
}; |
@ -0,0 +1,210 @@ |
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2018 |
||||||
|
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <common.h> |
||||||
|
#include <display_options.h> |
||||||
|
#include <dm.h> |
||||||
|
#include <dm/test.h> |
||||||
|
#include <test/ut.h> |
||||||
|
#include <video_osd.h> |
||||||
|
#include <asm/test.h> |
||||||
|
|
||||||
|
#include "../../drivers/video/sandbox_osd.h" |
||||||
|
|
||||||
|
const uint memsize = 2 * 10 * 10; |
||||||
|
|
||||||
|
static void split(u8 *mem, uint size, u8 *text, u8 *colors) |
||||||
|
{ |
||||||
|
int i; |
||||||
|
u16 *p = (u16 *)mem; |
||||||
|
|
||||||
|
for (i = 0; i < size; i++) { |
||||||
|
colors[i] = p[i] % 0x100; |
||||||
|
text[i] = p[i] / 0x100; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void print_mem(u8 *mem, uint width, uint height) |
||||||
|
{ |
||||||
|
const uint memsize = 2 * 10 * 10; |
||||||
|
u8 colors[memsize / 2]; |
||||||
|
u8 text[memsize / 2]; |
||||||
|
int i; |
||||||
|
|
||||||
|
split(mem, memsize / 2, text, colors); |
||||||
|
|
||||||
|
for (i = 0; i < width * height; i++) { |
||||||
|
printf("%c", text[i]); |
||||||
|
if (i > 0 && ((i + 1) % width) == 0) |
||||||
|
printf("\n"); |
||||||
|
} |
||||||
|
|
||||||
|
printf("\n"); |
||||||
|
|
||||||
|
for (i = 0; i < width * height; i++) { |
||||||
|
printf("%c", colors[i]); |
||||||
|
if (i > 0 && ((i + 1) % width) == 0) |
||||||
|
printf("\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static int dm_test_osd_basics(struct unit_test_state *uts) |
||||||
|
{ |
||||||
|
struct udevice *dev; |
||||||
|
u8 mem[memsize + 1]; |
||||||
|
u8 colors[memsize / 2]; |
||||||
|
u8 text[memsize / 2]; |
||||||
|
struct video_osd_info info; |
||||||
|
|
||||||
|
ut_assertok(uclass_first_device_err(UCLASS_VIDEO_OSD, &dev)); |
||||||
|
|
||||||
|
video_osd_get_info(dev, &info); |
||||||
|
|
||||||
|
ut_asserteq(10, info.width); |
||||||
|
ut_asserteq(10, info.height); |
||||||
|
ut_asserteq(1, info.major_version); |
||||||
|
ut_asserteq(0, info.minor_version); |
||||||
|
|
||||||
|
ut_assertok(sandbox_osd_get_mem(dev, mem, memsize)); |
||||||
|
split(mem, memsize / 2, text, colors); |
||||||
|
|
||||||
|
ut_assertok(memcmp(text, " " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" ", memsize / 2)); |
||||||
|
|
||||||
|
ut_assertok(memcmp(colors, "kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk", memsize / 2)); |
||||||
|
|
||||||
|
print_mem(mem, 10, 10); |
||||||
|
|
||||||
|
ut_assertok(video_osd_print(dev, 1, 1, COLOR_RED, "Blah")); |
||||||
|
|
||||||
|
ut_assertok(sandbox_osd_get_mem(dev, mem, memsize)); |
||||||
|
split(mem, memsize / 2, text, colors); |
||||||
|
|
||||||
|
ut_assertok(memcmp(text, " " |
||||||
|
" Blah " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" ", memsize / 2)); |
||||||
|
|
||||||
|
ut_assertok(memcmp(colors, "kkkkkkkkkk" |
||||||
|
"krrrrkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk" |
||||||
|
"kkkkkkkkkk", memsize / 2)); |
||||||
|
|
||||||
|
print_mem(mem, 10, 10); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
DM_TEST(dm_test_osd_basics, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); |
||||||
|
|
||||||
|
static int dm_test_osd_extended(struct unit_test_state *uts) |
||||||
|
{ |
||||||
|
struct udevice *dev; |
||||||
|
u8 mem[memsize + 1]; |
||||||
|
u8 colors[memsize / 2]; |
||||||
|
u8 text[memsize / 2]; |
||||||
|
struct video_osd_info info; |
||||||
|
u16 val; |
||||||
|
|
||||||
|
ut_assertok(uclass_first_device_err(UCLASS_VIDEO_OSD, &dev)); |
||||||
|
|
||||||
|
ut_assertok(video_osd_set_size(dev, 20, 5)); |
||||||
|
|
||||||
|
video_osd_get_info(dev, &info); |
||||||
|
|
||||||
|
ut_asserteq(20, info.width); |
||||||
|
ut_asserteq(5, info.height); |
||||||
|
ut_asserteq(1, info.major_version); |
||||||
|
ut_asserteq(0, info.minor_version); |
||||||
|
|
||||||
|
ut_assertok(sandbox_osd_get_mem(dev, mem, memsize)); |
||||||
|
split(mem, memsize / 2, text, colors); |
||||||
|
|
||||||
|
ut_assertok(memcmp(text, " " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" " |
||||||
|
" ", memsize / 2)); |
||||||
|
|
||||||
|
ut_assertok(memcmp(colors, "kkkkkkkkkkkkkkkkkkkk" |
||||||
|
"kkkkkkkkkkkkkkkkkkkk" |
||||||
|
"kkkkkkkkkkkkkkkkkkkk" |
||||||
|
"kkkkkkkkkkkkkkkkkkkk" |
||||||
|
"kkkkkkkkkkkkkkkkkkkk", memsize / 2)); |
||||||
|
|
||||||
|
print_mem(mem, 20, 5); |
||||||
|
|
||||||
|
/* Draw green border */ |
||||||
|
val = '-' * 0x100 + 'g'; |
||||||
|
ut_assertok(video_osd_set_mem(dev, 1, 0, (u8 *)&val, 2, 18)); |
||||||
|
ut_assertok(video_osd_set_mem(dev, 1, 4, (u8 *)&val, 2, 18)); |
||||||
|
ut_assertok(video_osd_print(dev, 0, 1, COLOR_GREEN, "|")); |
||||||
|
ut_assertok(video_osd_print(dev, 0, 2, COLOR_GREEN, "|")); |
||||||
|
ut_assertok(video_osd_print(dev, 0, 3, COLOR_GREEN, "|")); |
||||||
|
ut_assertok(video_osd_print(dev, 19, 1, COLOR_GREEN, "|")); |
||||||
|
ut_assertok(video_osd_print(dev, 19, 2, COLOR_GREEN, "|")); |
||||||
|
ut_assertok(video_osd_print(dev, 19, 3, COLOR_GREEN, "|")); |
||||||
|
ut_assertok(video_osd_print(dev, 0, 0, COLOR_GREEN, "+")); |
||||||
|
ut_assertok(video_osd_print(dev, 19, 0, COLOR_GREEN, "+")); |
||||||
|
ut_assertok(video_osd_print(dev, 19, 4, COLOR_GREEN, "+")); |
||||||
|
ut_assertok(video_osd_print(dev, 0, 4, COLOR_GREEN, "+")); |
||||||
|
|
||||||
|
/* Add menu caption and entries */ |
||||||
|
ut_assertok(video_osd_print(dev, 5, 0, COLOR_GREEN, " OSD menu ")); |
||||||
|
ut_assertok(video_osd_print(dev, 2, 1, COLOR_BLUE, " * Entry 1")); |
||||||
|
ut_assertok(video_osd_print(dev, 2, 2, COLOR_BLUE, "(*) Entry 2")); |
||||||
|
ut_assertok(video_osd_print(dev, 2, 3, COLOR_BLUE, " * Entry 3")); |
||||||
|
|
||||||
|
ut_assertok(sandbox_osd_get_mem(dev, mem, memsize)); |
||||||
|
split(mem, memsize / 2, text, colors); |
||||||
|
|
||||||
|
print_mem(mem, 20, 5); |
||||||
|
|
||||||
|
ut_assertok(memcmp(text, "+---- OSD menu ----+" |
||||||
|
"| * Entry 1 |" |
||||||
|
"| (*) Entry 2 |" |
||||||
|
"| * Entry 3 |" |
||||||
|
"+------------------+", memsize / 2)); |
||||||
|
|
||||||
|
ut_assertok(memcmp(colors, "gggggggggggggggggggg" |
||||||
|
"gkbbbbbbbbbbbkkkkkkg" |
||||||
|
"gkbbbbbbbbbbbkkkkkkg" |
||||||
|
"gkbbbbbbbbbbbkkkkkkg" |
||||||
|
"gggggggggggggggggggg", memsize / 2)); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
DM_TEST(dm_test_osd_extended, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); |
Loading…
Reference in new issue