Commit | Line | Data |
---|---|---|
457c8996 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
1da177e4 LT |
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> | |
1da177e4 LT |
11 | #include <linux/console.h> |
12 | #include <linux/vt_kern.h> | |
894673ee | 13 | #include <linux/screen_info.h> |
1da177e4 LT |
14 | #include <linux/init.h> |
15 | #include <linux/module.h> | |
16 | ||
17 | /* | |
18 | * Dummy console driver | |
19 | */ | |
20 | ||
21 | #if defined(__arm__) | |
3ea33510 PA |
22 | #define DUMMY_COLUMNS screen_info.orig_video_cols |
23 | #define DUMMY_ROWS screen_info.orig_video_lines | |
8f5b1e65 | 24 | #else |
1da177e4 | 25 | /* set by Kconfig. Use 80x25 for 640x480 and 160x64 for 1280x1024 */ |
1da177e4 LT |
26 | #define DUMMY_COLUMNS CONFIG_DUMMY_CONSOLE_COLUMNS |
27 | #define DUMMY_ROWS CONFIG_DUMMY_CONSOLE_ROWS | |
1da177e4 LT |
28 | #endif |
29 | ||
83d83beb HG |
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 | ||
1da177e4 LT |
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 | ||
c396a5bf KC |
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) { } | |
c396a5bf KC |
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) | |
1da177e4 | 117 | { |
c396a5bf | 118 | return 0; |
1da177e4 LT |
119 | } |
120 | ||
c396a5bf KC |
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 | } | |
1da177e4 LT |
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 = { | |
c396a5bf KC |
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, | |
1da177e4 | 159 | }; |
a4de0526 | 160 | EXPORT_SYMBOL_GPL(dummy_con); |