forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-02-20 e636c8d336489bf3eed5878299e6cc045bbad077
kernel/drivers/video/console/sticon.c
....@@ -2,7 +2,7 @@
22 * linux/drivers/video/console/sticon.c - console driver using HP's STI firmware
33 *
44 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
5
- * Copyright (C) 2002 Helge Deller <deller@gmx.de>
5
+ * Copyright (C) 2002-2020 Helge Deller <deller@gmx.de>
66 *
77 * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
88 * which were
....@@ -43,6 +43,9 @@
4343 #include <linux/kd.h>
4444 #include <linux/selection.h>
4545 #include <linux/module.h>
46
+#include <linux/slab.h>
47
+#include <linux/font.h>
48
+#include <linux/crc32.h>
4649
4750 #include <asm/io.h>
4851
....@@ -52,27 +55,15 @@
5255 #define BLANK 0
5356 static int vga_is_gfx;
5457
58
+#define STI_DEF_FONT sticon_sti->font
59
+
60
+/* borrowed from fbcon.c */
61
+#define FNTREFCOUNT(fd) (fd->refcount)
62
+#define FNTCRC(fd) (fd->crc)
63
+static struct sti_cooked_font *font_data[MAX_NR_CONSOLES];
64
+
5565 /* this is the sti_struct used for this console */
5666 static struct sti_struct *sticon_sti;
57
-
58
-/* Software scrollback */
59
-static unsigned long softback_buf, softback_curr;
60
-static unsigned long softback_in;
61
-static unsigned long /* softback_top, */ softback_end;
62
-static int softback_lines;
63
-
64
-/* software cursor */
65
-static int cursor_drawn;
66
-#define CURSOR_DRAW_DELAY (1)
67
-#define DEFAULT_CURSOR_BLINK_RATE (20)
68
-
69
-static int vbl_cursor_cnt;
70
-
71
-static inline void cursor_undrawn(void)
72
-{
73
- vbl_cursor_cnt = 0;
74
- cursor_drawn = 0;
75
-}
7667
7768 static const char *sticon_startup(void)
7869 {
....@@ -81,72 +72,54 @@
8172
8273 static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
8374 {
84
- int redraw_cursor = 0;
85
-
8675 if (vga_is_gfx || console_blanked)
8776 return;
8877
8978 if (conp->vc_mode != KD_TEXT)
9079 return;
91
-#if 0
92
- if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) {
93
- cursor_undrawn();
94
- redraw_cursor = 1;
95
- }
96
-#endif
9780
98
- sti_putc(sticon_sti, c, ypos, xpos);
99
-
100
- if (redraw_cursor)
101
- vbl_cursor_cnt = CURSOR_DRAW_DELAY;
81
+ sti_putc(sticon_sti, c, ypos, xpos, font_data[conp->vc_num]);
10282 }
10383
10484 static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
10585 int count, int ypos, int xpos)
10686 {
107
- int redraw_cursor = 0;
108
-
10987 if (vga_is_gfx || console_blanked)
11088 return;
11189
11290 if (conp->vc_mode != KD_TEXT)
11391 return;
11492
115
-#if 0
116
- if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) &&
117
- (p->cursor_x < (xpos + count))) {
118
- cursor_undrawn();
119
- redraw_cursor = 1;
120
- }
121
-#endif
122
-
12393 while (count--) {
124
- sti_putc(sticon_sti, scr_readw(s++), ypos, xpos++);
94
+ sti_putc(sticon_sti, scr_readw(s++), ypos, xpos++,
95
+ font_data[conp->vc_num]);
12596 }
126
-
127
- if (redraw_cursor)
128
- vbl_cursor_cnt = CURSOR_DRAW_DELAY;
12997 }
13098
13199 static void sticon_cursor(struct vc_data *conp, int mode)
132100 {
133101 unsigned short car1;
134102
135
- car1 = conp->vc_screenbuf[conp->vc_x + conp->vc_y * conp->vc_cols];
103
+ /* no cursor update if screen is blanked */
104
+ if (vga_is_gfx || console_blanked)
105
+ return;
106
+
107
+ car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols];
136108 switch (mode) {
137109 case CM_ERASE:
138
- sti_putc(sticon_sti, car1, conp->vc_y, conp->vc_x);
110
+ sti_putc(sticon_sti, car1, conp->state.y, conp->state.x,
111
+ font_data[conp->vc_num]);
139112 break;
140113 case CM_MOVE:
141114 case CM_DRAW:
142
- switch (conp->vc_cursor_type & 0x0f) {
115
+ switch (CUR_SIZE(conp->vc_cursor_type)) {
143116 case CUR_UNDERLINE:
144117 case CUR_LOWER_THIRD:
145118 case CUR_LOWER_HALF:
146119 case CUR_TWO_THIRDS:
147120 case CUR_BLOCK:
148121 sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11),
149
- conp->vc_y, conp->vc_x);
122
+ conp->state.y, conp->state.x, font_data[conp->vc_num]);
150123 break;
151124 }
152125 break;
....@@ -165,17 +138,137 @@
165138
166139 switch (dir) {
167140 case SM_UP:
168
- sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols);
169
- sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_video_erase_char);
141
+ sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols,
142
+ font_data[conp->vc_num]);
143
+ sti_clear(sti, b - count, 0, count, conp->vc_cols,
144
+ conp->vc_video_erase_char, font_data[conp->vc_num]);
170145 break;
171146
172147 case SM_DOWN:
173
- sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols);
174
- sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_video_erase_char);
148
+ sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols,
149
+ font_data[conp->vc_num]);
150
+ sti_clear(sti, t, 0, count, conp->vc_cols,
151
+ conp->vc_video_erase_char, font_data[conp->vc_num]);
175152 break;
176153 }
177154
178155 return false;
156
+}
157
+
158
+static int sticon_set_def_font(int unit, struct console_font *op)
159
+{
160
+ if (font_data[unit] != STI_DEF_FONT) {
161
+ if (--FNTREFCOUNT(font_data[unit]) == 0) {
162
+ kfree(font_data[unit]->raw_ptr);
163
+ kfree(font_data[unit]);
164
+ }
165
+ font_data[unit] = STI_DEF_FONT;
166
+ }
167
+
168
+ return 0;
169
+}
170
+
171
+static int sticon_set_font(struct vc_data *vc, struct console_font *op)
172
+{
173
+ struct sti_struct *sti = sticon_sti;
174
+ int vc_cols, vc_rows, vc_old_cols, vc_old_rows;
175
+ int unit = vc->vc_num;
176
+ int w = op->width;
177
+ int h = op->height;
178
+ int size, i, bpc, pitch;
179
+ struct sti_rom_font *new_font;
180
+ struct sti_cooked_font *cooked_font;
181
+ unsigned char *data = op->data, *p;
182
+
183
+ if ((w < 6) || (h < 6) || (w > 32) || (h > 32)
184
+ || (op->charcount != 256 && op->charcount != 512))
185
+ return -EINVAL;
186
+ pitch = ALIGN(w, 8) / 8;
187
+ bpc = pitch * h;
188
+ size = bpc * op->charcount;
189
+
190
+ new_font = kmalloc(sizeof(*new_font) + size, STI_LOWMEM);
191
+ if (!new_font)
192
+ return -ENOMEM;
193
+
194
+ new_font->first_char = 0;
195
+ new_font->last_char = op->charcount - 1;
196
+ new_font->width = w;
197
+ new_font->height = h;
198
+ new_font->font_type = STI_FONT_HPROMAN8;
199
+ new_font->bytes_per_char = bpc;
200
+ new_font->underline_height = 0;
201
+ new_font->underline_pos = 0;
202
+
203
+ cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
204
+ if (!cooked_font) {
205
+ kfree(new_font);
206
+ return -ENOMEM;
207
+ }
208
+ cooked_font->raw = new_font;
209
+ cooked_font->raw_ptr = new_font;
210
+ cooked_font->width = w;
211
+ cooked_font->height = h;
212
+ FNTREFCOUNT(cooked_font) = 0; /* usage counter */
213
+
214
+ p = (unsigned char *) new_font;
215
+ p += sizeof(*new_font);
216
+ for (i = 0; i < op->charcount; i++) {
217
+ memcpy(p, data, bpc);
218
+ data += pitch*32;
219
+ p += bpc;
220
+ }
221
+ FNTCRC(cooked_font) = crc32(0, new_font, size + sizeof(*new_font));
222
+ sti_font_convert_bytemode(sti, cooked_font);
223
+ new_font = cooked_font->raw_ptr;
224
+
225
+ /* check if font is already used by other console */
226
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
227
+ if (font_data[i] != STI_DEF_FONT
228
+ && (FNTCRC(font_data[i]) == FNTCRC(cooked_font))) {
229
+ kfree(new_font);
230
+ kfree(cooked_font);
231
+ /* current font is the same as the new one */
232
+ if (i == unit)
233
+ return 0;
234
+ cooked_font = font_data[i];
235
+ new_font = cooked_font->raw_ptr;
236
+ break;
237
+ }
238
+ }
239
+
240
+ /* clear screen with old font: we now may have less rows */
241
+ vc_old_rows = vc->vc_rows;
242
+ vc_old_cols = vc->vc_cols;
243
+ sti_clear(sticon_sti, 0, 0, vc_old_rows, vc_old_cols,
244
+ vc->vc_video_erase_char, font_data[vc->vc_num]);
245
+
246
+ /* delete old font in case it is a user font */
247
+ sticon_set_def_font(unit, NULL);
248
+
249
+ FNTREFCOUNT(cooked_font)++;
250
+ font_data[unit] = cooked_font;
251
+
252
+ vc_cols = sti_onscreen_x(sti) / cooked_font->width;
253
+ vc_rows = sti_onscreen_y(sti) / cooked_font->height;
254
+ vc_resize(vc, vc_cols, vc_rows);
255
+
256
+ /* need to repaint screen if cols & rows are same as old font */
257
+ if (vc_cols == vc_old_cols && vc_rows == vc_old_rows)
258
+ update_screen(vc);
259
+
260
+ return 0;
261
+}
262
+
263
+static int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name)
264
+{
265
+ return sticon_set_def_font(vc->vc_num, op);
266
+}
267
+
268
+static int sticon_font_set(struct vc_data *vc, struct console_font *font,
269
+ unsigned int flags)
270
+{
271
+ return sticon_set_font(vc, font);
179272 }
180273
181274 static void sticon_init(struct vc_data *c, int init)
....@@ -184,23 +277,25 @@
184277 int vc_cols, vc_rows;
185278
186279 sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0);
187
- vc_cols = sti_onscreen_x(sti) / sti->font_width;
188
- vc_rows = sti_onscreen_y(sti) / sti->font_height;
280
+ vc_cols = sti_onscreen_x(sti) / sti->font->width;
281
+ vc_rows = sti_onscreen_y(sti) / sti->font->height;
189282 c->vc_can_do_color = 1;
190283
191284 if (init) {
192285 c->vc_cols = vc_cols;
193286 c->vc_rows = vc_rows;
194287 } else {
195
- /* vc_rows = (c->vc_rows > vc_rows) ? vc_rows : c->vc_rows; */
196
- /* vc_cols = (c->vc_cols > vc_cols) ? vc_cols : c->vc_cols; */
197288 vc_resize(c, vc_cols, vc_rows);
198
-/* vc_resize_con(vc_rows, vc_cols, c->vc_num); */
199289 }
200290 }
201291
202292 static void sticon_deinit(struct vc_data *c)
203293 {
294
+ int i;
295
+
296
+ /* free memory used by user font */
297
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
298
+ sticon_set_def_font(i, NULL);
204299 }
205300
206301 static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
....@@ -209,17 +304,13 @@
209304 if (!height || !width)
210305 return;
211306
212
- sti_clear(sticon_sti, sy, sx, height, width, conp->vc_video_erase_char);
307
+ sti_clear(sticon_sti, sy, sx, height, width,
308
+ conp->vc_video_erase_char, font_data[conp->vc_num]);
213309 }
214310
215311 static int sticon_switch(struct vc_data *conp)
216312 {
217313 return 1; /* needs refreshing */
218
-}
219
-
220
-static int sticon_set_origin(struct vc_data *conp)
221
-{
222
- return 0;
223314 }
224315
225316 static int sticon_blank(struct vc_data *c, int blank, int mode_switch)
....@@ -229,67 +320,17 @@
229320 vga_is_gfx = 0;
230321 return 1;
231322 }
232
- sticon_set_origin(c);
233
- sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK);
323
+ sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK,
324
+ font_data[c->vc_num]);
234325 if (mode_switch)
235326 vga_is_gfx = 1;
236327 return 1;
237328 }
238329
239
-static u16 *sticon_screen_pos(struct vc_data *conp, int offset)
240
-{
241
- int line;
242
- unsigned long p;
243
-
244
- if (conp->vc_num != fg_console || !softback_lines)
245
- return (u16 *)(conp->vc_origin + offset);
246
- line = offset / conp->vc_size_row;
247
- if (line >= softback_lines)
248
- return (u16 *)(conp->vc_origin + offset - softback_lines * conp->vc_size_row);
249
- p = softback_curr + offset;
250
- if (p >= softback_end)
251
- p += softback_buf - softback_end;
252
- return (u16 *)p;
253
-}
254
-
255
-static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos,
256
- int *px, int *py)
257
-{
258
- int x, y;
259
- unsigned long ret;
260
- if (pos >= conp->vc_origin && pos < conp->vc_scr_end) {
261
- unsigned long offset = (pos - conp->vc_origin) / 2;
262
-
263
- x = offset % conp->vc_cols;
264
- y = offset / conp->vc_cols;
265
- if (conp->vc_num == fg_console)
266
- y += softback_lines;
267
- ret = pos + (conp->vc_cols - x) * 2;
268
- } else if (conp->vc_num == fg_console && softback_lines) {
269
- unsigned long offset = pos - softback_curr;
270
-
271
- if (pos < softback_curr)
272
- offset += softback_end - softback_buf;
273
- offset /= 2;
274
- x = offset % conp->vc_cols;
275
- y = offset / conp->vc_cols;
276
- ret = pos + (conp->vc_cols - x) * 2;
277
- if (ret == softback_end)
278
- ret = softback_buf;
279
- if (ret == softback_in)
280
- ret = conp->vc_origin;
281
- } else {
282
- /* Should not happen */
283
- x = y = 0;
284
- ret = conp->vc_origin;
285
- }
286
- if (px) *px = x;
287
- if (py) *py = y;
288
- return ret;
289
-}
290
-
291
-static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens,
292
- u8 blink, u8 underline, u8 reverse, u8 italic)
330
+static u8 sticon_build_attr(struct vc_data *conp, u8 color,
331
+ enum vc_intensity intens,
332
+ bool blink, bool underline, bool reverse,
333
+ bool italic)
293334 {
294335 u8 fg = color & 7;
295336 u8 bg = (color & 0x70) >> 4;
....@@ -316,10 +357,6 @@
316357 }
317358 }
318359
319
-static void sticon_save_screen(struct vc_data *conp)
320
-{
321
-}
322
-
323360 static const struct consw sti_con = {
324361 .owner = THIS_MODULE,
325362 .con_startup = sticon_startup,
....@@ -332,19 +369,18 @@
332369 .con_scroll = sticon_scroll,
333370 .con_switch = sticon_switch,
334371 .con_blank = sticon_blank,
335
- .con_set_origin = sticon_set_origin,
336
- .con_save_screen = sticon_save_screen,
372
+ .con_font_set = sticon_font_set,
373
+ .con_font_default = sticon_font_default,
337374 .con_build_attr = sticon_build_attr,
338375 .con_invert_region = sticon_invert_region,
339
- .con_screen_pos = sticon_screen_pos,
340
- .con_getxy = sticon_getxy,
341376 };
342377
343378
344379
345380 static int __init sticonsole_init(void)
346381 {
347
- int err;
382
+ int err, i;
383
+
348384 /* already initialized ? */
349385 if (sticon_sti)
350386 return 0;
....@@ -353,14 +389,16 @@
353389 if (!sticon_sti)
354390 return -ENODEV;
355391
356
- if (conswitchp == &dummy_con) {
357
- printk(KERN_INFO "sticon: Initializing STI text console.\n");
358
- console_lock();
359
- err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, 1);
360
- console_unlock();
361
- return err;
362
- }
363
- return 0;
392
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
393
+ font_data[i] = STI_DEF_FONT;
394
+
395
+ pr_info("sticon: Initializing STI text console.\n");
396
+ console_lock();
397
+ err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1,
398
+ PAGE0->mem_cons.cl_class != CL_DUPLEX);
399
+ console_unlock();
400
+
401
+ return err;
364402 }
365403
366404 module_init(sticonsole_init);