]> git.baikalelectronics.ru Git - kernel.git/commitdiff
fbcon: Add option to enable legacy hardware acceleration
authorHelge Deller <deller@gmx.de>
Wed, 2 Feb 2022 13:55:31 +0000 (14:55 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 2 Feb 2022 14:16:26 +0000 (15:16 +0100)
Add a config option CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION to
enable bitblt and fillrect hardware acceleration in the framebuffer
console. If disabled, such acceleration will not be used, even if it is
supported by the graphics hardware driver.

If you plan to use DRM as your main graphics output system, you should
disable this option since it will prevent compiling in code which isn't
used later on when DRM takes over.

For all other configurations, e.g. if none of your graphic cards support
DRM (yet), DRM isn't available for your architecture, or you can't be
sure that the graphic card in the target system will support DRM, you
most likely want to enable this option.

In the non-accelerated case (e.g. when DRM is used), the inlined
fb_scrollmode() function is hardcoded to return SCROLL_REDRAW and as such the
compiler is able to optimize much unneccesary code away.

In this v3 patch version I additionally changed the GETVYRES() and GETVXRES()
macros to take a pointer to the fbcon_display struct. This fixes the build when
console rotation is enabled and helps the compiler again to optimize out code.

Signed-off-by: Helge Deller <deller@gmx.de>
Cc: stable@vger.kernel.org # v5.10+
Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20220202135531.92183-4-deller@gmx.de
drivers/video/console/Kconfig
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbcon.h
drivers/video/fbdev/core/fbcon_ccw.c
drivers/video/fbdev/core/fbcon_cw.c
drivers/video/fbdev/core/fbcon_rotate.h
drivers/video/fbdev/core/fbcon_ud.c

index 840d9813b0bc693cc9696d515beb701bf2e80393..fcc46380e7c91409f649b1e73c46ba25e794adf3 100644 (file)
@@ -78,6 +78,26 @@ config FRAMEBUFFER_CONSOLE
        help
          Low-level framebuffer-based console driver.
 
+config FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
+       bool "Enable legacy fbcon hardware acceleration code"
+       depends on FRAMEBUFFER_CONSOLE
+       default y if PARISC
+       default n
+       help
+         This option enables the fbcon (framebuffer text-based) hardware
+         acceleration for graphics drivers which were written for the fbdev
+         graphics interface.
+
+         On modern machines, on mainstream machines (like x86-64) or when
+         using a modern Linux distribution those fbdev drivers usually aren't used.
+         So enabling this option wouldn't have any effect, which is why you want
+         to disable this option on such newer machines.
+
+         If you compile this kernel for older machines which still require the
+         fbdev drivers, you may want to say Y.
+
+         If unsure, select n.
+
 config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
        bool "Map the console to the primary display device"
        depends on FRAMEBUFFER_CONSOLE
index 0cc2a36b674a374632f214bc99a8371f19b365f3..f36829eeb5a93032d8939cfb22dd8792c7f3a435 100644 (file)
@@ -1136,11 +1136,13 @@ static void fbcon_init(struct vc_data *vc, int init)
 
        ops->graphics = 0;
 
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
        if ((cap & FBINFO_HWACCEL_COPYAREA) &&
            !(cap & FBINFO_HWACCEL_DISABLED))
                p->scrollmode = SCROLL_MOVE;
        else /* default to something safe */
                p->scrollmode = SCROLL_REDRAW;
+#endif
 
        /*
         *  ++guenther: console.c:vc_allocate() relies on initializing
@@ -1705,7 +1707,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
                        count = vc->vc_rows;
                if (logo_shown >= 0)
                        goto redraw_up;
-               switch (p->scrollmode) {
+               switch (fb_scrollmode(p)) {
                case SCROLL_MOVE:
                        fbcon_redraw_blit(vc, info, p, t, b - t - count,
                                     count);
@@ -1795,7 +1797,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
                        count = vc->vc_rows;
                if (logo_shown >= 0)
                        goto redraw_down;
-               switch (p->scrollmode) {
+               switch (fb_scrollmode(p)) {
                case SCROLL_MOVE:
                        fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
                                     -count);
@@ -1946,12 +1948,12 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy,
                   height, width);
 }
 
-static void updatescrollmode(struct fbcon_display *p,
+static void updatescrollmode_accel(struct fbcon_display *p,
                                        struct fb_info *info,
                                        struct vc_data *vc)
 {
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
        struct fbcon_ops *ops = info->fbcon_par;
-       int fh = vc->vc_font.height;
        int cap = info->flags;
        u16 t = 0;
        int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep,
@@ -1972,12 +1974,6 @@ static void updatescrollmode(struct fbcon_display *p,
        int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) &&
                !(cap & FBINFO_HWACCEL_DISABLED);
 
-       p->vrows = vyres/fh;
-       if (yres > (fh * (vc->vc_rows + 1)))
-               p->vrows -= (yres - (fh * vc->vc_rows)) / fh;
-       if ((yres % fh) && (vyres % fh < yres % fh))
-               p->vrows--;
-
        if (good_wrap || good_pan) {
                if (reading_fast || fast_copyarea)
                        p->scrollmode = good_wrap ?
@@ -1991,6 +1987,27 @@ static void updatescrollmode(struct fbcon_display *p,
                else
                        p->scrollmode = SCROLL_REDRAW;
        }
+#endif
+}
+
+static void updatescrollmode(struct fbcon_display *p,
+                                       struct fb_info *info,
+                                       struct vc_data *vc)
+{
+       struct fbcon_ops *ops = info->fbcon_par;
+       int fh = vc->vc_font.height;
+       int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+       int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual,
+                                  info->var.xres_virtual);
+
+       p->vrows = vyres/fh;
+       if (yres > (fh * (vc->vc_rows + 1)))
+               p->vrows -= (yres - (fh * vc->vc_rows)) / fh;
+       if ((yres % fh) && (vyres % fh < yres % fh))
+               p->vrows--;
+
+       /* update scrollmode in case hardware acceleration is used */
+       updatescrollmode_accel(p, info, vc);
 }
 
 #define PITCH(w) (((w) + 7) >> 3)
@@ -2148,7 +2165,7 @@ static int fbcon_switch(struct vc_data *vc)
 
        updatescrollmode(p, info, vc);
 
-       switch (p->scrollmode) {
+       switch (fb_scrollmode(p)) {
        case SCROLL_WRAP_MOVE:
                scrollback_phys_max = p->vrows - vc->vc_rows;
                break;
index 5246d0f2574b85ff180b61522a9eacebf881e6f6..969d41ecede5fe1e61b3a6dd0472a55c41afb358 100644 (file)
@@ -29,7 +29,9 @@ struct fbcon_display {
     /* Filled in by the low-level console driver */
     const u_char *fontdata;
     int userfont;                   /* != 0 if fontdata kmalloc()ed */
-    u_short scrollmode;             /* Scroll Method */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
+    u_short scrollmode;             /* Scroll Method, use fb_scrollmode() */
+#endif
     u_short inverse;                /* != 0 text black on white as default */
     short yscroll;                  /* Hardware scrolling */
     int vrows;                      /* number of virtual rows */
@@ -208,6 +210,17 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
 #define SCROLL_REDRAW     0x004
 #define SCROLL_PAN_REDRAW  0x005
 
+static inline u_short fb_scrollmode(struct fbcon_display *fb)
+{
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
+       return fb->scrollmode;
+#else
+       /* hardcoded to SCROLL_REDRAW if acceleration was disabled. */
+       return SCROLL_REDRAW;
+#endif
+}
+
+
 #ifdef CONFIG_FB_TILEBLITTING
 extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
 #endif
index 9cd2c4b05c3286b12cfe4ac2bb186a3f4be1c89a..2789ace7963427fe80b82c19eb706daa21e316d9 100644 (file)
@@ -65,7 +65,7 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
 {
        struct fbcon_ops *ops = info->fbcon_par;
        struct fb_copyarea area;
-       u32 vyres = GETVYRES(ops->p->scrollmode, info);
+       u32 vyres = GETVYRES(ops->p, info);
 
        area.sx = sy * vc->vc_font.height;
        area.sy = vyres - ((sx + width) * vc->vc_font.width);
@@ -83,7 +83,7 @@ static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy,
        struct fbcon_ops *ops = info->fbcon_par;
        struct fb_fillrect region;
        int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
-       u32 vyres = GETVYRES(ops->p->scrollmode, info);
+       u32 vyres = GETVYRES(ops->p, info);
 
        region.color = attr_bgcol_ec(bgshift,vc,info);
        region.dx = sy * vc->vc_font.height;
@@ -140,7 +140,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info,
        u32 cnt, pitch, size;
        u32 attribute = get_attribute(info, scr_readw(s));
        u8 *dst, *buf = NULL;
-       u32 vyres = GETVYRES(ops->p->scrollmode, info);
+       u32 vyres = GETVYRES(ops->p, info);
 
        if (!ops->fontbuffer)
                return;
@@ -229,7 +229,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
        int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
        int err = 1, dx, dy;
        char *src;
-       u32 vyres = GETVYRES(ops->p->scrollmode, info);
+       u32 vyres = GETVYRES(ops->p, info);
 
        if (!ops->fontbuffer)
                return;
@@ -387,7 +387,7 @@ static int ccw_update_start(struct fb_info *info)
 {
        struct fbcon_ops *ops = info->fbcon_par;
        u32 yoffset;
-       u32 vyres = GETVYRES(ops->p->scrollmode, info);
+       u32 vyres = GETVYRES(ops->p, info);
        int err;
 
        yoffset = (vyres - info->var.yres) - ops->var.xoffset;
index 88d89fad3f05e324f555023eb0b27dec13c47100..86a254c1b2b7b6bd039fde6cbc588f009b7ed338 100644 (file)
@@ -50,7 +50,7 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
 {
        struct fbcon_ops *ops = info->fbcon_par;
        struct fb_copyarea area;
-       u32 vxres = GETVXRES(ops->p->scrollmode, info);
+       u32 vxres = GETVXRES(ops->p, info);
 
        area.sx = vxres - ((sy + height) * vc->vc_font.height);
        area.sy = sx * vc->vc_font.width;
@@ -68,7 +68,7 @@ static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy,
        struct fbcon_ops *ops = info->fbcon_par;
        struct fb_fillrect region;
        int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
-       u32 vxres = GETVXRES(ops->p->scrollmode, info);
+       u32 vxres = GETVXRES(ops->p, info);
 
        region.color = attr_bgcol_ec(bgshift,vc,info);
        region.dx = vxres - ((sy + height) * vc->vc_font.height);
@@ -125,7 +125,7 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info,
        u32 cnt, pitch, size;
        u32 attribute = get_attribute(info, scr_readw(s));
        u8 *dst, *buf = NULL;
-       u32 vxres = GETVXRES(ops->p->scrollmode, info);
+       u32 vxres = GETVXRES(ops->p, info);
 
        if (!ops->fontbuffer)
                return;
@@ -212,7 +212,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
        int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
        int err = 1, dx, dy;
        char *src;
-       u32 vxres = GETVXRES(ops->p->scrollmode, info);
+       u32 vxres = GETVXRES(ops->p, info);
 
        if (!ops->fontbuffer)
                return;
@@ -369,7 +369,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
 static int cw_update_start(struct fb_info *info)
 {
        struct fbcon_ops *ops = info->fbcon_par;
-       u32 vxres = GETVXRES(ops->p->scrollmode, info);
+       u32 vxres = GETVXRES(ops->p, info);
        u32 xoffset;
        int err;
 
index e233444cda664783d055b372929cafd2f4ac2e89..01cbe303b8a29592d3236add1f8b46db85d2b74f 100644 (file)
 #define _FBCON_ROTATE_H
 
 #define GETVYRES(s,i) ({                           \
-        (s == SCROLL_REDRAW || s == SCROLL_MOVE) ? \
+        (fb_scrollmode(s) == SCROLL_REDRAW || fb_scrollmode(s) == SCROLL_MOVE) ? \
         (i)->var.yres : (i)->var.yres_virtual; })
 
 #define GETVXRES(s,i) ({                           \
-        (s == SCROLL_REDRAW || s == SCROLL_MOVE || !(i)->fix.xpanstep) ? \
+        (fb_scrollmode(s) == SCROLL_REDRAW || fb_scrollmode(s) == SCROLL_MOVE || !(i)->fix.xpanstep) ? \
         (i)->var.xres : (i)->var.xres_virtual; })
 
 
index 8d5e66b1bdfbb7dbe8262b77708b488a421b4b79..23bc045769d088e8f9690c03dc8228d71635daa0 100644 (file)
@@ -50,8 +50,8 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy,
 {
        struct fbcon_ops *ops = info->fbcon_par;
        struct fb_copyarea area;
-       u32 vyres = GETVYRES(ops->p->scrollmode, info);
-       u32 vxres = GETVXRES(ops->p->scrollmode, info);
+       u32 vyres = GETVYRES(ops->p, info);
+       u32 vxres = GETVXRES(ops->p, info);
 
        area.sy = vyres - ((sy + height) * vc->vc_font.height);
        area.sx = vxres - ((sx + width) * vc->vc_font.width);
@@ -69,8 +69,8 @@ static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy,
        struct fbcon_ops *ops = info->fbcon_par;
        struct fb_fillrect region;
        int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
-       u32 vyres = GETVYRES(ops->p->scrollmode, info);
-       u32 vxres = GETVXRES(ops->p->scrollmode, info);
+       u32 vyres = GETVYRES(ops->p, info);
+       u32 vxres = GETVXRES(ops->p, info);
 
        region.color = attr_bgcol_ec(bgshift,vc,info);
        region.dy = vyres - ((sy + height) * vc->vc_font.height);
@@ -162,8 +162,8 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info,
        u32 mod = vc->vc_font.width % 8, cnt, pitch, size;
        u32 attribute = get_attribute(info, scr_readw(s));
        u8 *dst, *buf = NULL;
-       u32 vyres = GETVYRES(ops->p->scrollmode, info);
-       u32 vxres = GETVXRES(ops->p->scrollmode, info);
+       u32 vyres = GETVYRES(ops->p, info);
+       u32 vxres = GETVXRES(ops->p, info);
 
        if (!ops->fontbuffer)
                return;
@@ -259,8 +259,8 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
        int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
        int err = 1, dx, dy;
        char *src;
-       u32 vyres = GETVYRES(ops->p->scrollmode, info);
-       u32 vxres = GETVXRES(ops->p->scrollmode, info);
+       u32 vyres = GETVYRES(ops->p, info);
+       u32 vxres = GETVXRES(ops->p, info);
 
        if (!ops->fontbuffer)
                return;
@@ -410,8 +410,8 @@ static int ud_update_start(struct fb_info *info)
 {
        struct fbcon_ops *ops = info->fbcon_par;
        int xoffset, yoffset;
-       u32 vyres = GETVYRES(ops->p->scrollmode, info);
-       u32 vxres = GETVXRES(ops->p->scrollmode, info);
+       u32 vyres = GETVYRES(ops->p, info);
+       u32 vxres = GETVXRES(ops->p, info);
        int err;
 
        xoffset = vxres - info->var.xres - ops->var.xoffset;