1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * linux/drivers/video/dummycon.c -- A dummy console driver 4 * 5 * To be used if there's no other console driver (e.g. for plain VGA text) 6 * available, usually until fbcon takes console over. 7 */ 8 9 #include <linux/types.h> 10 #include <linux/kdev_t.h> 11 #include <linux/console.h> 12 #include <linux/vt_kern.h> 13 #include <linux/screen_info.h> 14 #include <linux/init.h> 15 #include <linux/module.h> 16 17 /* 18 * Dummy console driver 19 */ 20 21 #if defined(__arm__) 22 #define DUMMY_COLUMNS screen_info.orig_video_cols 23 #define DUMMY_ROWS screen_info.orig_video_lines 24 #else 25 /* set by Kconfig. Use 80x25 for 640x480 and 160x64 for 1280x1024 */ 26 #define DUMMY_COLUMNS CONFIG_DUMMY_CONSOLE_COLUMNS 27 #define DUMMY_ROWS CONFIG_DUMMY_CONSOLE_ROWS 28 #endif 29 30 #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER 31 /* These are both protected by the console_lock */ 32 static RAW_NOTIFIER_HEAD(dummycon_output_nh); 33 static bool dummycon_putc_called; 34 35 void dummycon_register_output_notifier(struct notifier_block *nb) 36 { 37 raw_notifier_chain_register(&dummycon_output_nh, nb); 38 39 if (dummycon_putc_called) 40 nb->notifier_call(nb, 0, NULL); 41 } 42 43 void dummycon_unregister_output_notifier(struct notifier_block *nb) 44 { 45 raw_notifier_chain_unregister(&dummycon_output_nh, nb); 46 } 47 48 static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) 49 { 50 dummycon_putc_called = true; 51 raw_notifier_call_chain(&dummycon_output_nh, 0, NULL); 52 } 53 54 static void dummycon_putcs(struct vc_data *vc, const unsigned short *s, 55 int count, int ypos, int xpos) 56 { 57 int i; 58 59 if (!dummycon_putc_called) { 60 /* Ignore erases */ 61 for (i = 0 ; i < count; i++) { 62 if (s[i] != vc->vc_video_erase_char) 63 break; 64 } 65 if (i == count) 66 return; 67 68 dummycon_putc_called = true; 69 } 70 71 raw_notifier_call_chain(&dummycon_output_nh, 0, NULL); 72 } 73 74 static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch) 75 { 76 /* Redraw, so that we get putc(s) for output done while blanked */ 77 return 1; 78 } 79 #else 80 static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) { } 81 static void dummycon_putcs(struct vc_data *vc, const unsigned short *s, 82 int count, int ypos, int xpos) { } 83 static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch) 84 { 85 return 0; 86 } 87 #endif 88 89 static const char *dummycon_startup(void) 90 { 91 return "dummy device"; 92 } 93 94 static void dummycon_init(struct vc_data *vc, int init) 95 { 96 vc->vc_can_do_color = 1; 97 if (init) { 98 vc->vc_cols = DUMMY_COLUMNS; 99 vc->vc_rows = DUMMY_ROWS; 100 } else 101 vc_resize(vc, DUMMY_COLUMNS, DUMMY_ROWS); 102 } 103 104 static void dummycon_deinit(struct vc_data *vc) { } 105 static void dummycon_clear(struct vc_data *vc, int sy, int sx, int height, 106 int width) { } 107 static void dummycon_cursor(struct vc_data *vc, int mode) { } 108 109 static bool dummycon_scroll(struct vc_data *vc, unsigned int top, 110 unsigned int bottom, enum con_scroll dir, 111 unsigned int lines) 112 { 113 return false; 114 } 115 116 static int dummycon_switch(struct vc_data *vc) 117 { 118 return 0; 119 } 120 121 static int dummycon_font_set(struct vc_data *vc, struct console_font *font, 122 unsigned int flags) 123 { 124 return 0; 125 } 126 127 static int dummycon_font_default(struct vc_data *vc, 128 struct console_font *font, char *name) 129 { 130 return 0; 131 } 132 133 static int dummycon_font_copy(struct vc_data *vc, int con) 134 { 135 return 0; 136 } 137 138 /* 139 * The console `switch' structure for the dummy console 140 * 141 * Most of the operations are dummies. 142 */ 143 144 const struct consw dummy_con = { 145 .owner = THIS_MODULE, 146 .con_startup = dummycon_startup, 147 .con_init = dummycon_init, 148 .con_deinit = dummycon_deinit, 149 .con_clear = dummycon_clear, 150 .con_putc = dummycon_putc, 151 .con_putcs = dummycon_putcs, 152 .con_cursor = dummycon_cursor, 153 .con_scroll = dummycon_scroll, 154 .con_switch = dummycon_switch, 155 .con_blank = dummycon_blank, 156 .con_font_set = dummycon_font_set, 157 .con_font_default = dummycon_font_default, 158 .con_font_copy = dummycon_font_copy, 159 }; 160 EXPORT_SYMBOL_GPL(dummy_con); 161