Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | // SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2018 * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc */ #include <display.h> #include <dm.h> #include <malloc.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 = sizeof(struct sandbox_osd_priv), }; |