@@ -160,12 +160,12 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri
return ret;
}
-int cursor_show(void *line, struct video_priv *vid_priv, uint height,
+int cursor_show(struct vidconsole_cursor *curs, struct video_priv *vid_priv,
bool direction)
{
int step, line_step, pbytes, ret;
+ void *line, *dst;
uint value;
- void *dst;
ret = check_bpix_support(vid_priv->bpix);
if (ret)
@@ -180,16 +180,22 @@ int cursor_show(void *line, struct video_priv *vid_priv, uint height,
line_step = vid_priv->line_length;
}
+ /* Figure out where to write the cursor in the frame buffer */
+ line = vid_priv->fb + curs->y * vid_priv->line_length +
+ curs->x * VNBYTES(vid_priv->bpix);
+
value = vid_priv->colour_fg;
- for (int row = 0; row < height; row++) {
+ for (int row = 0; row < curs->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;
+ return 0;
}
int console_probe(struct udevice *dev)
@@ -75,17 +75,18 @@ int console_normal_putc_xy(struct udevice *dev, uint x_frac, uint y, int cp)
return console_fixed_putc_xy(dev, x_frac, y, cp, priv->fontdata);
}
-static int __maybe_unused console_set_cursor_visible(struct udevice *dev,
- bool visible, uint x,
- uint y, uint index)
+static __maybe_unused int console_get_cursor_info(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;
+ struct vidconsole_cursor *curs = &vc_priv->curs;
int pbytes = VNBYTES(vid_priv->bpix);
- void *start;
+ void *start, *line;
/* for now, this is not used outside expo */
if (!IS_ENABLED(CONFIG_EXPO))
@@ -98,7 +99,12 @@ static int __maybe_unused console_set_cursor_visible(struct udevice *dev,
x -= 1;
start = vid_priv->fb + y * vid_priv->line_length + x * pbytes;
- cursor_show(start, vid_priv, vc_priv->y_charsize, NORMAL_DIRECTION);
+ line = start;
+
+ /* Store line pointer and height in cursor struct */
+ curs->x = x;
+ curs->y = y;
+ curs->height = vc_priv->y_charsize;
return 0;
}
@@ -116,7 +122,7 @@ struct vidconsole_ops console_ops = {
.get_font = console_simple_get_font,
.select_font = console_simple_select_font,
#ifdef CONFIG_CURSOR
- .set_cursor_visible = console_set_cursor_visible,
+ .get_cursor_info = console_get_cursor_info,
#endif
};
@@ -993,33 +993,30 @@ 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)
+static int truetype_get_cursor_info(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);
- void *line;
+ struct vidconsole_cursor *curs = &vc_priv->curs;
uint height;
if (xpl_phase() <= PHASE_SPL)
return -ENOSYS;
- 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;
+ if (visible) {
+ index = priv->pos_ptr;
+ 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;
+ }
/* Get font height from current font type */
if (priv->cur_fontdata)
@@ -1027,16 +1024,13 @@ static int truetype_set_cursor_visible(struct udevice *dev, bool visible,
else
height = priv->cur_met->font_size;
- /* Figure out where to write the cursor in the frame buffer */
- line = vid_priv->fb + y * vid_priv->line_length +
- x * VNBYTES(vid_priv->bpix);
-
- /* Use the shared cursor drawing function */
- cursor_show(line, vid_priv, height, NORMAL_DIRECTION);
+ /* Store line pointer and height in cursor struct */
+ curs->x = x;
+ curs->y = y;
+ curs->index = index;
+ curs->height = height;
- video_damage(dev->parent, x, y, VIDCONSOLE_CURSOR_WIDTH, height);
-
- return video_sync(vid, true);
+ return 0;
}
const char *console_truetype_get_font_size(struct udevice *dev, uint *sizep)
@@ -1101,7 +1095,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
+ .get_cursor_info = truetype_get_cursor_info,
};
U_BOOT_DRIVER(vidconsole_truetype) = {
@@ -17,6 +17,7 @@
#include <dm.h>
#include <video.h>
#include <video_console.h>
+#include "vidconsole_internal.h"
#include <video_font.h> /* Bitmap font for code page 437 */
#include <linux/ctype.h>
@@ -702,21 +703,59 @@ int vidconsole_entry_restore(struct udevice *dev, struct abuf *buf)
}
#ifdef CONFIG_CURSOR
-int vidconsole_set_cursor_visible(struct udevice *dev, bool visible,
- uint x, uint y, uint index)
+int vidconsole_show_cursor(struct udevice *dev, uint x, uint y, uint index)
{
+ struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct vidconsole_ops *ops = vidconsole_get_ops(dev);
+ struct vidconsole_cursor *curs = &priv->curs;
int ret;
- if (ops->set_cursor_visible) {
- ret = ops->set_cursor_visible(dev, visible, x, y, index);
- if (ret != -ENOSYS)
+ /* find out where the cursor should be drawn */
+ if (ops->get_cursor_info) {
+ ret = ops->get_cursor_info(dev, true, x, y, index);
+ if (ret && ret != -ENOSYS)
+ return ret;
+ }
+
+ /* If the driver stored cursor line and height, use them for drawing */
+ if (curs->height) {
+ struct udevice *vid = dev_get_parent(dev);
+ struct video_priv *vid_priv = dev_get_uclass_priv(vid);
+
+ /*
+ * avoid drawing off the display - we assume that the driver
+ * ensures that curs->y < vid_priv->ysize
+ */
+ curs->height = min(curs->height, vid_priv->ysize - curs->y);
+
+ ret = cursor_show(curs, vid_priv, NORMAL_DIRECTION);
+ if (ret)
+ return ret;
+
+ /* Update display damage for cursor area */
+ video_damage(vid, curs->x, curs->y, VIDCONSOLE_CURSOR_WIDTH,
+ curs->height);
+ }
+
+ priv->curs.visible = true;
+
+ return 0;
+}
+
+int vidconsole_set_cursor_visible(struct udevice *dev, bool visible,
+ uint x, uint y, uint index)
+{
+ if (visible) {
+ int ret;
+
+ ret = vidconsole_show_cursor(dev, x, y, index);
+ if (ret)
return ret;
}
return 0;
}
-#endif
+#endif /* CONFIG_CURSOR */
void vidconsole_push_colour(struct udevice *dev, enum colour_idx fg,
enum colour_idx bg, struct vidconsole_colour *old)
@@ -9,6 +9,10 @@
#include <charset.h>
#include <config.h>
+struct udevice;
+struct vidconsole_cursor;
+struct video_priv;
+
#define FLIPPED_DIRECTION 1
#define NORMAL_DIRECTION 0
@@ -98,10 +102,10 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri
/**
* cursor_show() - 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.
+ * @curs: cursor information
+ * @vid_priv: video-device info
+ * @direction: controls cursor orientation (normal or flipped)
+ *
* When normal: When flipped:
*|-----------------------------------------------|
*| * | line stepping |
@@ -116,7 +120,7 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri
*
* Return: 0, if success, or else error code.
*/
-int cursor_show(void *line, struct video_priv *vid_priv, uint height,
+int cursor_show(struct vidconsole_cursor *curs, struct video_priv *vid_priv,
bool direction);
/**
@@ -330,9 +330,9 @@ struct vidconsole_ops {
int (*entry_restore)(struct udevice *dev, struct abuf *buf);
/**
- * set_cursor_visible() - Show or hide the cursor
+ * get_cursor_info() - Get cursor position info
*
- * Shows or hides a cursor at the current position
+ * Calculates and stores cursor position information
*
* @dev: Console device to use
* @visible: true to show the cursor, false to hide it
@@ -341,8 +341,8 @@ struct vidconsole_ops {
* @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);
+ int (*get_cursor_info)(struct udevice *dev, bool visible,
+ uint x, uint y, uint index);
};
/* Get a pointer to the driver operations for a video console device */
@@ -430,6 +430,21 @@ int vidconsole_entry_save(struct udevice *dev, struct abuf *buf);
int vidconsole_entry_restore(struct udevice *dev, struct abuf *buf);
#ifdef CONFIG_CURSOR
+/**
+ * vidconsole_show_cursor() - Show the cursor
+ *
+ * Shows a cursor at the specified position. The position is passed in, but for
+ * the truetype console it is not actually used, since it tracks where the
+ * cursor must go.
+ *
+ * @dev: Console device to use
+ * @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_show_cursor(struct udevice *dev, uint x, uint y, uint index);
+
/**
* vidconsole_set_cursor_visible() - Show or hide the cursor
*
@@ -445,6 +460,12 @@ int vidconsole_entry_restore(struct udevice *dev, struct abuf *buf);
int vidconsole_set_cursor_visible(struct udevice *dev, bool visible,
uint x, uint y, uint index);
#else
+static inline int vidconsole_show_cursor(struct udevice *dev, uint x, uint y,
+ uint index)
+{
+ return 0;
+}
+
static inline int vidconsole_set_cursor_visible(struct udevice *dev,
bool visible, uint x, uint y,
uint index)