kernel/syscons: Temporarily disable a6aa39351756c.
[dragonfly.git] / sys / dev / misc / syscons / sckmsrndr.c
1 /*-
2  * Copyright (c) 2014 Imre Vadász <imre@vdsz.com>
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The DragonFly Project
6  * by Sascha Wildner <saw@online.de>.
7  *
8  * Simple font scaling code by Sascha Wildner and Matthew Dillon
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer as
15  *    the first lines of this file unmodified.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "opt_syscons.h"
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/thread.h>
38 #include <sys/thread2.h>
39
40 #include <machine/console.h>
41
42 #include <dev/drm/include/linux/fb.h>
43
44 #include "syscons.h"
45
46 #include <bus/isa/isareg.h>
47
48 static vr_draw_t                kms_draw;
49 static vr_draw_cursor_t         kms_cursor;
50 static vr_blink_cursor_t        kms_blink;
51 static vr_draw_mouse_t          kms_mouse;
52
53 static void                     kms_nop(scr_stat *scp, ...);
54
55 static sc_rndr_sw_t kmsrndrsw = {
56         (vr_draw_border_t *)kms_nop,
57         kms_draw,
58         (vr_set_cursor_t *)kms_nop,
59         kms_cursor,
60         kms_blink,
61 #ifndef SC_NO_CUTPASTE
62         kms_mouse,
63 #else
64         (vr_draw_mouse_t *)kms_nop;
65 #endif
66 };
67 RENDERER(kms, V_INFO_MM_TEXT, kmsrndrsw, kms_set);
68
69 #ifndef SC_NO_MODE_CHANGE
70 static sc_rndr_sw_t grrndrsw = {
71         (vr_draw_border_t *)kms_nop,
72         (vr_draw_t *)kms_nop,
73         (vr_set_cursor_t *)kms_nop,
74         (vr_draw_cursor_t *)kms_nop,
75         (vr_blink_cursor_t *)kms_nop,
76         (vr_draw_mouse_t *)kms_nop,
77 };
78 RENDERER(kms, V_INFO_MM_OTHER, grrndrsw, kms_set);
79 #endif /* SC_NO_MODE_CHANGE */
80
81 RENDERER_MODULE(kms, kms_set);
82
83 static uint32_t colormap[16] = {
84         0x00000000,     /* BLACK */
85         0x000000aa,     /* BLUE */
86         0x0000aa00,     /* GREEN */
87         0x0000aaaa,     /* CYAN */
88         0x00aa0000,     /* RED */
89         0x00aa00aa,     /* MAGENTA */
90         0x00aa5500,     /* BROWN */
91         0x00aaaaaa,     /* WHITE */
92         0x00555555,     /* HIGHLIGHT BLACK */
93         0x005555ff,     /* HIGHLIGHT BLUE */
94         0x0055ff55,     /* HIGHLIGHT GREEN */
95         0x0055ffff,     /* HIGHLIGHT CYAN */
96         0x00ff5555,     /* HIGHLIGHT RED */
97         0x00ff55ff,     /* HIGHLIGHT MAGENTA */
98         0x00ffff55,     /* HIGHLIGHT BROWN */
99         0x00ffffff,     /* HIGHLIGHT WHITE */
100 };
101
102 #ifndef SC_NO_CUTPASTE
103 static u_short mouse_and_mask[16] = {
104         0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
105         0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
106 };
107 static u_short mouse_or_mask[16] = {
108         0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
109         0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
110 };
111 #endif
112
113 static void
114 kms_nop(scr_stat *scp, ...)
115 {
116 }
117
118 /*
119  * Scaled font rendering.  Simple blit blitter copy operation with bitmap
120  * scaling.  Scales the bitmap char_data(sw x sh) to the output bitmap
121  * draw_pos(dw x dh).
122  *
123  * This function does not do fractional scaling.
124  *
125  * SET  - Sets both the fg and bg pen
126  *
127  * MASK - Sets only the fg pen based on the source mask and leaves
128  *        the background untouched.
129  */
130 #define BLIT_SET        0
131 #define BLIT_MASK       1
132
133 static void
134 blit_blk(scr_stat *scp, u_char *char_data, int sw, int sh,
135          vm_offset_t draw_pos, int pixel_size, int dw, int dh,
136          int line_width, uint32_t fg, uint32_t bg, int how)
137 {
138         vm_offset_t p;
139         int pos;
140         int x;          /* destination iterator (whole pixels) */
141         int y;
142         int sx, sx_inc; /* source iterator (fractional) */
143         int sy, sy_inc;
144         uint8_t c;
145
146         /*
147          * Calculate fractional iterator for source
148          */
149         if (dw)
150                 sx_inc = (sw << 16) / dw;
151         else
152                 sx_inc = 0;
153
154         if (dh)
155                 sy_inc = (sh << 16) / dh;
156         else
157                 sy_inc = 0;
158
159         sy = 0;
160         c = 0;
161
162         /*
163          * For each pixel row in the target
164          */
165         for (y = 0; y < dh; ++y) {
166                 sx = 0;
167                 p = draw_pos;
168
169                 /*
170                  * Render all pixel columns in the target by calculating
171                  * which bit in the source is applicable.
172                  */
173                 switch(how) {
174                 case BLIT_SET:
175                         for (x = 0; x < dw; ++x) {
176                                 if ((sx & 0x00070000) == 0)
177                                         c = char_data[sx >> 19];
178                                 pos = ~(sx >> 16) & 7;
179                                 writel(p, (c & (1 << pos) ? fg : bg));
180                                 p += pixel_size;
181                                 sx += sx_inc;
182                         }
183                         break;
184                 case BLIT_MASK:
185                         for (x = 0; x < dw; ++x) {
186                                 if ((sx & 0x00070000) == 0)
187                                         c = char_data[sx >> 19];
188                                 pos = ~(sx >> 16) & 7;
189                                 if (c & (1 << pos))
190                                         writel(p, fg);
191                                 p += pixel_size;
192                                 sx += sx_inc;
193                         }
194                         break;
195                 }
196                 draw_pos += line_width;
197                 sy += sy_inc;
198                 if (sy >= 0x10000) {
199                         char_data += (sy >> 16) * (sw >> 3);
200                         sy &= 0x0FFFF;
201                 }
202         }
203 }
204
205 /* KMS renderer */
206
207 static void
208 kms_draw(scr_stat *scp, int from, int count,
209          int flip, void (*func_yield)(void))
210 {
211         sc_softc_t *sc = scp->sc;
212         u_char *char_data;
213         int a, i;
214         uint32_t fg, bg;
215         vm_offset_t draw_pos, p;
216         int line_width, pixel_size;
217
218         line_width = sc->fbi->stride;
219         pixel_size = 4;
220
221         draw_pos = sc->fbi->vaddr +
222             scp->blk_width * pixel_size * (from % scp->xsize) +
223             scp->blk_height * line_width * (from / scp->xsize);
224
225         if (from + count > scp->xsize * scp->ysize)
226                 count = scp->xsize * scp->ysize - from;
227
228         for (i = from; count-- > 0; i++) {
229                 p = draw_pos;
230                 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
231                                         scp->font_height]);
232
233                 a = sc_vtb_geta(&scp->vtb, i);
234                 if (flip) {
235                         fg = colormap[((a & 0xf000) >> 4) >> 8];
236                         bg = colormap[(a & 0x0f00) >> 8];
237                 } else {
238                         fg = colormap[(a & 0x0f00) >> 8];
239                         bg = colormap[((a & 0xf000) >> 4) >> 8];
240                 }
241                 blit_blk(scp, char_data, scp->font_width, scp->font_height,
242                          p, pixel_size, scp->blk_width, scp->blk_height,
243                          line_width, fg, bg, BLIT_SET);
244                 draw_pos += scp->blk_width * pixel_size;
245                 if ((i % scp->xsize) == scp->xsize - 1) {
246                         draw_pos +=
247                             (scp->blk_height - 1) * line_width +
248                             scp->xpad * pixel_size;
249                 }
250
251 #if 0 /* XXX temporarily disabled */
252                 /*
253                  * Updating the framebuffer can take a very long time,
254                  * if the system is operating normally we try to at
255                  * least allow pending interrupts to run.
256                  */
257                 if ((count & 255) == 0 && func_yield && panicstr == NULL)
258                         func_yield();
259 #endif
260         }
261 }
262
263 static void
264 draw_kmscursor(scr_stat *scp, int at, int on, int flip)
265 {
266         sc_softc_t *sc = scp->sc;
267         int line_width, pixel_size;
268         int cursor_base;
269         int blk_base;
270         int a;
271         uint32_t fg, bg;
272         unsigned char *char_data;
273         vm_offset_t draw_pos;
274
275         line_width = sc->fbi->stride;
276         pixel_size = 4;
277         cursor_base = /* scp->font_height - */ scp->cursor_base;
278         blk_base = scp->blk_height * cursor_base / scp->font_height;
279
280         draw_pos = sc->fbi->vaddr +
281             scp->blk_width * pixel_size * (at % scp->xsize) +
282             scp->blk_height * line_width * (at / scp->xsize) +
283             blk_base * line_width;
284
285         a = sc_vtb_geta(&scp->vtb, at);
286         if (flip) {
287                 fg = colormap[((on) ? (a & 0x0f00) :
288                     ((a & 0xf000) >> 4)) >> 8];
289                 bg = colormap[((on) ? ((a & 0xf000) >> 4) :
290                     (a & 0x0f00)) >> 8];
291         } else {
292                 fg = colormap[((on) ? ((a & 0xf000) >> 4) :
293                     (a & 0x0f00)) >> 8];
294                 bg = colormap[((on) ? (a & 0x0f00) :
295                     ((a & 0xf000) >> 4)) >> 8];
296         }
297
298         char_data = &scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height];
299         char_data += cursor_base;
300
301         blit_blk(scp, char_data,
302                  scp->font_width, scp->font_height - cursor_base,
303                  draw_pos, pixel_size,
304                  scp->blk_width, scp->blk_height - blk_base,
305                  line_width, fg, bg, BLIT_SET);
306 }
307
308 static int pxlblinkrate = 0;
309
310 static void
311 kms_cursor(scr_stat *scp, int at, int blink, int on, int flip)
312 {
313         if (scp->cursor_height <= 0)    /* the text cursor is disabled */
314                 return;
315
316         if (on) {
317                 if (!blink) {
318                         scp->status |= VR_CURSOR_ON;
319                         draw_kmscursor(scp, at, on, flip);
320                 } else if (++pxlblinkrate & 4) {
321                         pxlblinkrate = 0;
322                         scp->status ^= VR_CURSOR_ON;
323                         draw_kmscursor(scp, at,
324                             scp->status & VR_CURSOR_ON, flip);
325                 }
326         } else {
327                 if (scp->status & VR_CURSOR_ON)
328                         draw_kmscursor(scp, at, on, flip);
329                 scp->status &= ~VR_CURSOR_ON;
330         }
331         if (blink)
332                 scp->status |= VR_CURSOR_BLINK;
333         else
334                 scp->status &= ~VR_CURSOR_BLINK;
335 }
336
337 static void
338 kms_blink(scr_stat *scp, int at, int flip)
339 {
340         if (!(scp->status & VR_CURSOR_BLINK))
341                 return;
342         if (!(++pxlblinkrate & 4))
343                 return;
344         pxlblinkrate = 0;
345         scp->status ^= VR_CURSOR_ON;
346         draw_kmscursor(scp, at, scp->status & VR_CURSOR_ON, flip);
347 }
348
349 #ifndef SC_NO_CUTPASTE
350
351 static void
352 draw_kmsmouse(scr_stat *scp, int x, int y)
353 {
354         sc_softc_t *sc = scp->sc;
355         int line_width, pixel_size;
356         int blk_width, blk_height;
357         vm_offset_t draw_pos;
358
359         line_width = sc->fbi->stride;
360         pixel_size = 4;
361
362         if (x + scp->font_width < scp->font_width * scp->xsize)
363                 blk_width = scp->blk_width;
364         else
365                 blk_width = scp->font_width * scp->xsize - x;
366
367         if (y + scp->font_height < scp->font_height * scp->ysize)
368                 blk_height = scp->blk_height;
369         else
370                 blk_height = scp->font_height * scp->ysize - y;
371
372         draw_pos = sc->fbi->vaddr + y * scp->blk_height / scp->font_height *
373                    line_width +
374                    x * scp->blk_width / scp->font_width * pixel_size;
375         blit_blk(scp, (unsigned char *)mouse_and_mask, 16, 16,
376                  draw_pos, pixel_size, blk_width, blk_height,
377                  line_width, colormap[0], 0, BLIT_MASK);
378         blit_blk(scp, (unsigned char *)mouse_or_mask, 16, 16,
379                  draw_pos, pixel_size, blk_width, blk_height,
380                  line_width, colormap[15], 0, BLIT_MASK);
381 }
382
383 static void
384 remove_kmsmouse(scr_stat *scp, int x, int y)
385 {
386         int col, row;
387         int pos;
388         int i;
389
390         /* erase the mouse cursor image */
391         col = x / scp->font_width - scp->xoff;
392         row = y / scp->font_height - scp->yoff;
393         pos = row * scp->xsize + col;
394         i = (col < scp->xsize - 1) ? 2 : 1;
395         (*scp->rndr->draw)(scp, pos, i, FALSE, NULL);
396         if (row < scp->ysize - 1)
397                 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE, NULL);
398 }
399
400 static void
401 kms_mouse(scr_stat *scp, int x, int y, int on)
402 {
403         if (on)
404                 draw_kmsmouse(scp, x, y);
405         else
406                 remove_kmsmouse(scp, x, y);
407 }
408
409 #endif /* SC_NO_CUTPASTE */