This adds VT console support. Signed-off-by: Noralf Trønnes <noralf@xxxxxxxxxxx> --- 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 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel