diff options
-rw-r--r-- | drivers/video/console_core.c | 31 | ||||
-rw-r--r-- | drivers/video/console_normal.c | 29 | ||||
-rw-r--r-- | drivers/video/console_truetype.c | 103 | ||||
-rw-r--r-- | drivers/video/vidconsole-uclass.c | 15 | ||||
-rw-r--r-- | drivers/video/vidconsole_internal.h | 24 | ||||
-rw-r--r-- | include/video_console.h | 35 |
6 files changed, 237 insertions, 0 deletions
diff --git a/drivers/video/console_core.c b/drivers/video/console_core.c index b5d0e3dcec..d17764d0b0 100644 --- a/drivers/video/console_core.c +++ b/drivers/video/console_core.c @@ -176,6 +176,37 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri return ret; } +int draw_cursor_vertically(void **line, struct video_priv *vid_priv, + uint height, bool direction) +{ + int step, line_step, pbytes, ret; + uint value; + void *dst; + + ret = check_bpix_support(vid_priv->bpix); + if (ret) + return ret; + + pbytes = VNBYTES(vid_priv->bpix); + if (direction) { + step = -pbytes; + line_step = -vid_priv->line_length; + } else { + step = pbytes; + line_step = vid_priv->line_length; + } + + value = vid_priv->colour_fg; + + for (int row = 0; row < height; row++) { + dst = *line; + for (int col = 0; col < VIDCONSOLE_CURSOR_WIDTH; col++) + fill_pixel_and_goto_next(&dst, value, pbytes, step); + *line += line_step; + } + return ret; +} + int console_probe(struct udevice *dev) { return console_set_font(dev, fonts); diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c index 413c7abee9..a0231293f3 100644 --- a/drivers/video/console_normal.c +++ b/drivers/video/console_normal.c @@ -97,6 +97,34 @@ static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, char ch) return VID_TO_POS(fontdata->width); } +static int console_set_cursor_visible(struct udevice *dev, bool visible, + uint x, uint y, uint index) +{ + struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); + struct udevice *vid = dev->parent; + struct video_priv *vid_priv = dev_get_uclass_priv(vid); + struct console_simple_priv *priv = dev_get_priv(dev); + struct video_fontdata *fontdata = priv->fontdata; + int pbytes = VNBYTES(vid_priv->bpix); + void *start, *line; + + /* for now, this is not used outside expo */ + if (!IS_ENABLED(CONFIG_EXPO)) + return -ENOSYS; + + x += index * fontdata->width; + start = vid_priv->fb + y * vid_priv->line_length + x * pbytes; + + /* place the cursor 1 pixel before the start of the next char */ + x -= 1; + + line = start; + draw_cursor_vertically(&line, vid_priv, vc_priv->y_charsize, + NORMAL_DIRECTION); + + return 0; +} + struct vidconsole_ops console_ops = { .putc_xy = console_putc_xy, .move_rows = console_move_rows, @@ -104,6 +132,7 @@ struct vidconsole_ops console_ops = { .get_font_size = console_simple_get_font_size, .get_font = console_simple_get_font, .select_font = console_simple_select_font, + .set_cursor_visible = console_set_cursor_visible, }; U_BOOT_DRIVER(vidconsole_normal) = { diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 1ce01a96bb..242b8b7134 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -831,6 +831,108 @@ static int truetype_entry_restore(struct udevice *dev, struct abuf *buf) return 0; } +static int truetype_set_cursor_visible(struct udevice *dev, bool visible, + uint x, uint y, uint index) +{ + struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); + struct udevice *vid = dev->parent; + struct video_priv *vid_priv = dev_get_uclass_priv(vid); + struct console_tt_priv *priv = dev_get_priv(dev); + struct console_tt_metrics *met = priv->cur_met; + uint row, width, height, xoff; + void *start, *line; + uint out, val; + int ret; + + if (!visible) + return 0; + + /* + * figure out where to place the cursor. This driver ignores the + * passed-in values, since an entry_restore() must have been done before + * calling this function. + */ + if (index < priv->pos_ptr) + x = VID_TO_PIXEL(priv->pos[index].xpos_frac); + else + x = VID_TO_PIXEL(vc_priv->xcur_frac); + + y = vc_priv->ycur; + height = met->font_size; + xoff = 0; + + val = vid_priv->colour_bg ? 0 : 255; + width = VIDCONSOLE_CURSOR_WIDTH; + + /* Figure out where to write the cursor in the frame buffer */ + start = vid_priv->fb + y * vid_priv->line_length + + x * VNBYTES(vid_priv->bpix); + line = start; + + /* draw a vertical bar in the correct position */ + for (row = 0; row < height; row++) { + switch (vid_priv->bpix) { + case VIDEO_BPP8: + if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { + u8 *dst = line + xoff; + int i; + + out = val; + for (i = 0; i < width; i++) { + if (vid_priv->colour_fg) + *dst++ |= out; + else + *dst++ &= out; + } + } + break; + case VIDEO_BPP16: { + u16 *dst = (u16 *)line + xoff; + int i; + + if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { + for (i = 0; i < width; i++) { + out = val >> 3 | + (val >> 2) << 5 | + (val >> 3) << 11; + if (vid_priv->colour_fg) + *dst++ |= out; + else + *dst++ &= out; + } + } + break; + } + case VIDEO_BPP32: { + u32 *dst = (u32 *)line + xoff; + int i; + + if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { + for (i = 0; i < width; i++) { + int out; + + out = val | val << 8 | val << 16; + if (vid_priv->colour_fg) + *dst++ |= out; + else + *dst++ &= out; + } + } + break; + } + default: + return -ENOSYS; + } + + line += vid_priv->line_length; + } + ret = vidconsole_sync_copy(dev, start, line); + if (ret) + return ret; + + return video_sync(vid, true); +} + const char *console_truetype_get_font_size(struct udevice *dev, uint *sizep) { struct console_tt_priv *priv = dev_get_priv(dev); @@ -886,6 +988,7 @@ struct vidconsole_ops console_truetype_ops = { .nominal = truetype_nominal, .entry_save = truetype_entry_save, .entry_restore = truetype_entry_restore, + .set_cursor_visible = truetype_set_cursor_visible }; U_BOOT_DRIVER(vidconsole_truetype) = { diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 2f3f685a55..22d55df71f 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -672,6 +672,21 @@ int vidconsole_entry_restore(struct udevice *dev, struct abuf *buf) return 0; } +int vidconsole_set_cursor_visible(struct udevice *dev, bool visible, + uint x, uint y, uint index) +{ + struct vidconsole_ops *ops = vidconsole_get_ops(dev); + int ret; + + if (ops->set_cursor_visible) { + ret = ops->set_cursor_visible(dev, visible, x, y, index); + if (ret != -ENOSYS) + return ret; + } + + return 0; +} + void vidconsole_push_colour(struct udevice *dev, enum colour_idx fg, enum colour_idx bg, struct vidconsole_colour *old) { diff --git a/drivers/video/vidconsole_internal.h b/drivers/video/vidconsole_internal.h index c41edd4524..0ec581b266 100644 --- a/drivers/video/vidconsole_internal.h +++ b/drivers/video/vidconsole_internal.h @@ -93,6 +93,30 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri struct video_fontdata *fontdata, bool direction); /** + * draw_cursor_vertically() - Draw a simple vertical cursor + * + * @line: pointer to framebuffer buffer: upper left cursor corner + * @vid_priv: driver private data + * @height: height of the cursor in pixels + * @param direction controls cursor orientation. Can be normal or flipped. + * When normal: When flipped: + *|-----------------------------------------------| + *| * | line stepping | + *| ^ * * * * * | | | + *| | * * | v * * | + *| | | * * * * * | + *| line stepping | * | + *| | | + *| stepping -> | <<- stepping | + *|---!!we're starting from upper left char corner| + *|-----------------------------------------------| + * + * Return: 0, if success, or else error code. + */ +int draw_cursor_vertically(void **line, struct video_priv *vid_priv, + uint height, bool direction); + +/** * console probe function. * * @param dev a pointer to device. diff --git a/include/video_console.h b/include/video_console.h index 87f9a58857..bde67fa9a5 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -16,6 +16,11 @@ struct video_priv; #define VID_TO_PIXEL(x) ((x) / VID_FRAC_DIV) #define VID_TO_POS(x) ((x) * VID_FRAC_DIV) +enum { + /* cursor width in pixels */ + VIDCONSOLE_CURSOR_WIDTH = 2, +}; + /** * struct vidconsole_priv - uclass-private data about a console device * @@ -264,6 +269,21 @@ struct vidconsole_ops { * Return: 0 if OK, -ve on error */ int (*entry_restore)(struct udevice *dev, struct abuf *buf); + + /** + * set_cursor_visible() - Show or hide the cursor + * + * Shows or hides a cursor at the current position + * + * @dev: Console device to use + * @visible: true to show the cursor, false to hide it + * @x: X position in pixels + * @y: Y position in pixels + * @index: Character position (0 = at start) + * Return: 0 if OK, -ve on error + */ + int (*set_cursor_visible)(struct udevice *dev, bool visible, + uint x, uint y, uint index); }; /* Get a pointer to the driver operations for a video console device */ @@ -343,6 +363,21 @@ int vidconsole_entry_save(struct udevice *dev, struct abuf *buf); int vidconsole_entry_restore(struct udevice *dev, struct abuf *buf); /** + * vidconsole_set_cursor_visible() - Show or hide the cursor + * + * Shows or hides a cursor at the current position + * + * @dev: Console device to use + * @visible: true to show the cursor, false to hide it + * @x: X position in pixels + * @y: Y position in pixels + * @index: Character position (0 = at start) + * Return: 0 if OK, -ve on error + */ +int vidconsole_set_cursor_visible(struct udevice *dev, bool visible, + uint x, uint y, uint index); + +/** * vidconsole_push_colour() - Temporarily change the font colour * * @dev: Device to adjust |