This adds VT console support.

Signed-off-by: Noralf Trønnes <noralf at tronnes.org>
---
 drivers/gpu/drm/drm-text/Makefile          |   1 +
 drivers/gpu/drm/drm-text/drm-text-buffer.c |   2 +
 drivers/gpu/drm/drm-text/drm-text-vt.c     | 197 +++++++++++++++++++++++++++++
 drivers/gpu/drm/drm-text/drm-text.h        |  14 ++
 4 files changed, 214 insertions(+)
 create mode 100644 drivers/gpu/drm/drm-text/drm-text-vt.c

diff --git a/drivers/gpu/drm/drm-text/Makefile 
b/drivers/gpu/drm/drm-text/Makefile
index be042b0..4427522 100644
--- a/drivers/gpu/drm/drm-text/Makefile
+++ b/drivers/gpu/drm/drm-text/Makefile
@@ -1,4 +1,5 @@
 drm-text-y := drm-text-console.o drm-text-buffer.o
+drm-text-$(CONFIG_VT) += drm-text-vt.o
 drm-text-$(CONFIG_DEBUG_FS) += drm-text-debugfs.o

 obj-m += drm-text.o
diff --git a/drivers/gpu/drm/drm-text/drm-text-buffer.c 
b/drivers/gpu/drm/drm-text/drm-text-buffer.c
index 91beb48..0f995d3 100644
--- a/drivers/gpu/drm/drm-text/drm-text-buffer.c
+++ b/drivers/gpu/drm/drm-text/drm-text-buffer.c
@@ -317,6 +317,7 @@ static int __init drm_text_init(void)
        drm_text_scan_fbdev();

        ret = drm_text_console_init();
+       ret = drm_text_vt_init();

        return ret;
 }
@@ -327,6 +328,7 @@ static void __exit drm_text_exit(void)
        unsigned int i;

        drm_text_console_exit();
+       drm_text_vt_exit();
        drm_text_debugfs_exit();

        for (i = 0; i < MAX_DRM_TEXT_BUFFERS; i++)
diff --git a/drivers/gpu/drm/drm-text/drm-text-vt.c 
b/drivers/gpu/drm/drm-text/drm-text-vt.c
new file mode 100644
index 0000000..a999a41
--- /dev/null
+++ b/drivers/gpu/drm/drm-text/drm-text-vt.c
@@ -0,0 +1,197 @@
+#define DEBUG
+/*
+ * Copyright 2016 Noralf Trønnes
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/console.h>
+#include <linux/err.h>
+#include <linux/vt_buffer.h>
+#include <linux/vt_kern.h>
+
+#include "drm-text.h"
+
+static unsigned int drm_text_vt_map[MAX_DRM_TEXT_BUFFERS];
+
+/* TODO: Some kind of mapping might be needed */
+static inline struct drm_text_buffer *drm_text_vt_get(unsigned int index)
+{
+       return drm_text_get(drm_text_vt_map[index]);
+}
+
+static const char *drm_text_con_startup(void)
+{
+       drm_text_debug("%s\n", __func__);
+       return "drm-vt";
+}
+
+static void drm_text_con_init(struct vc_data *vc, int init)
+{
+       struct drm_text_buffer *text = drm_text_vt_get(vc->vc_num);
+
+       drm_text_log("%s[%u](init=%d)\n", __func__, vc->vc_num, init);
+
+       vc->vc_can_do_color = 1;
+
+       if (!text) {
+               drm_text_log("%s[%u] no DRM device\n", __func__, vc->vc_num);
+               return;
+       }
+
+       if (init) {
+               vc->vc_cols = text->cols;
+               vc->vc_rows = text->rows;
+       } else {
+               vc_resize(vc, text->cols, text->rows);
+       }
+
+       drm_text_enable(text);
+}
+
+static void drm_text_con_deinit(struct vc_data *vc)
+{
+       drm_text_debug("%s[%u]\n", __func__, vc->vc_num);
+       pr_info("%s\n", __func__);
+}
+
+static void drm_text_con_putcs(struct vc_data *vc, const unsigned short *s,
+                              int count, int y, int x)
+{
+       struct drm_text_buffer *text = drm_text_vt_get(vc->vc_num);
+       u16 *dest;
+
+       if (!text)
+               return;
+
+       dest = &text->text_buf[x + (y * text->cols)];
+
+       for (; count > 0; count--) {
+               scr_writew(scr_readw(s++), dest++);
+       }
+       drm_text_flush(text, false);
+}
+
+static void drm_text_con_putc(struct vc_data *vc, int ch, int y, int x)
+{
+       struct drm_text_buffer *text = drm_text_vt_get(vc->vc_num);
+       unsigned short chr;
+
+       if (!text)
+               return;
+
+       scr_writew(ch, &chr);
+       drm_text_con_putcs(vc, &chr, 1, y, x);
+}
+
+/* TODO: How do I actually test this? */
+static void drm_text_con_clear(struct vc_data *vc, int y, int x,
+                              int height, int width)
+{
+       struct drm_text_buffer *text = drm_text_vt_get(vc->vc_num);
+
+       drm_text_debug("%s[%u]\n", __func__, vc->vc_num);
+
+       if (!text)
+               return;
+
+       scr_memcpyw(text->text_buf, (unsigned short *)vc->vc_pos,
+                   vc->vc_cols * vc->vc_rows);
+       drm_text_flush(text, false);
+}
+
+static int drm_text_con_switch(struct vc_data *vc)
+{
+       drm_text_debug("%s[%u] %ux%u\n", __func__, vc->vc_num, vc->vc_cols, 
vc->vc_rows);
+
+       return 1; /* redrawing needed */
+}
+
+static void drm_text_con_set_palette(struct vc_data *vc, const unsigned char 
*table)
+{
+       drm_text_debug("%s[%u]\n", __func__, vc->vc_num);
+}
+
+static int drm_text_con_blank(struct vc_data *vc, int blank, int mode_switch)
+{
+       struct drm_text_buffer *text = drm_text_vt_get(vc->vc_num);
+       int ret;
+
+       drm_text_debug("%s[%u](blank=%d, mode_switch=%d)\n", __func__, 
vc->vc_num, blank, mode_switch);
+
+       if (!text)
+               return 0;
+
+       if (blank)
+               ret = drm_text_disable(text);
+       else
+               ret = drm_text_enable(text);
+
+       return ret;
+}
+
+static void drm_text_con_scrolldelta(struct vc_data *vc, int lines)
+{
+       drm_text_debug("%s[%u](lines=%d)\n", __func__, vc->vc_num, lines);
+}
+
+static void drm_text_con_cursor(struct vc_data *vc, int mode)
+{
+       /* TODO: Do we need a blinking cursor? */
+}
+
+static int drm_text_con_scroll(struct vc_data *vc, int t, int b, int dir, int 
lines)
+{
+       struct drm_text_buffer *text = drm_text_vt_get(vc->vc_num);
+
+       if (!text)
+               return 0;
+
+       switch (dir) {
+       case SM_UP:
+               drm_text_scroll(text, t, b, lines);
+               break;
+       case SM_DOWN:
+               drm_text_scroll(text, t, b, -lines);
+               break;
+       }
+
+       return 0;
+}
+
+static const struct consw drm_text_vt = {
+       .owner =                THIS_MODULE,
+       .con_startup =          drm_text_con_startup,
+       .con_init =             drm_text_con_init,
+       .con_deinit =           drm_text_con_deinit,
+       .con_clear =            drm_text_con_clear,
+       .con_putc =             drm_text_con_putc,
+       .con_putcs =            drm_text_con_putcs,
+       .con_cursor =           drm_text_con_cursor,
+       .con_scroll =           drm_text_con_scroll,
+       .con_switch =           drm_text_con_switch,
+       .con_blank =            drm_text_con_blank,
+       .con_set_palette =      drm_text_con_set_palette,
+       .con_scrolldelta =      drm_text_con_scrolldelta,
+};
+
+int drm_text_vt_init(void)
+{
+       int ret;
+
+       drm_text_debug("%s\n", __func__);
+
+       console_lock();
+       ret = do_take_over_console(&drm_text_vt, 0, MAX_NR_CONSOLES - 1, 0);
+       console_unlock();
+
+       return ret;
+}
+
+void drm_text_vt_exit(void)
+{
+       give_up_console(&drm_text_vt);
+}
diff --git a/drivers/gpu/drm/drm-text/drm-text.h 
b/drivers/gpu/drm/drm-text/drm-text.h
index 43ba76c..a01c283 100644
--- a/drivers/gpu/drm/drm-text/drm-text.h
+++ b/drivers/gpu/drm/drm-text/drm-text.h
@@ -43,6 +43,20 @@ int drm_text_console_init(void);
 void drm_text_console_exit(void);
 int drm_text_panic(struct notifier_block *this, unsigned long ev, void *ptr);

+#ifdef CONFIG_VT
+int drm_text_vt_init(void);
+void drm_text_vt_exit(void);
+#else
+int drm_text_vt_init(void)
+{
+       return 0;
+}
+
+void drm_text_vt_exit(void)
+{
+}
+#endif
+
 #ifdef DEBUG
 #define drm_text_debug(fmt, ...) \
        drm_text_log(fmt, ##__VA_ARGS__)
-- 
2.8.2

Reply via email to