diff mbox

[RFC,3/3] drm/text: Add VT console support

Message ID 1469715307-32708-4-git-send-email-noralf@tronnes.org (mailing list archive)
State New, archived
Headers show

Commit Message

Noralf Trønnes July 28, 2016, 2:15 p.m. UTC
This adds VT console support.

Signed-off-by: Noralf Trønnes <noralf@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 mbox

Patch

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__)