Commit a3f781a9 authored by Helge Deller's avatar Helge Deller Committed by Daniel Vetter

fbcon: Add option to enable legacy hardware acceleration

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: default avatarHelge Deller <deller@gmx.de>
Cc: stable@vger.kernel.org # v5.10+
Signed-off-by: default avatarHelge Deller <deller@gmx.de>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20220202135531.92183-4-deller@gmx.de
parent 87ab9f6b
...@@ -78,6 +78,26 @@ config FRAMEBUFFER_CONSOLE ...@@ -78,6 +78,26 @@ config FRAMEBUFFER_CONSOLE
help help
Low-level framebuffer-based console driver. 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 config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
bool "Map the console to the primary display device" bool "Map the console to the primary display device"
depends on FRAMEBUFFER_CONSOLE depends on FRAMEBUFFER_CONSOLE
......
...@@ -1136,11 +1136,13 @@ static void fbcon_init(struct vc_data *vc, int init) ...@@ -1136,11 +1136,13 @@ static void fbcon_init(struct vc_data *vc, int init)
ops->graphics = 0; ops->graphics = 0;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
if ((cap & FBINFO_HWACCEL_COPYAREA) && if ((cap & FBINFO_HWACCEL_COPYAREA) &&
!(cap & FBINFO_HWACCEL_DISABLED)) !(cap & FBINFO_HWACCEL_DISABLED))
p->scrollmode = SCROLL_MOVE; p->scrollmode = SCROLL_MOVE;
else /* default to something safe */ else /* default to something safe */
p->scrollmode = SCROLL_REDRAW; p->scrollmode = SCROLL_REDRAW;
#endif
/* /*
* ++guenther: console.c:vc_allocate() relies on initializing * ++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, ...@@ -1705,7 +1707,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
count = vc->vc_rows; count = vc->vc_rows;
if (logo_shown >= 0) if (logo_shown >= 0)
goto redraw_up; goto redraw_up;
switch (p->scrollmode) { switch (fb_scrollmode(p)) {
case SCROLL_MOVE: case SCROLL_MOVE:
fbcon_redraw_blit(vc, info, p, t, b - t - count, fbcon_redraw_blit(vc, info, p, t, b - t - count,
count); count);
...@@ -1795,7 +1797,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, ...@@ -1795,7 +1797,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
count = vc->vc_rows; count = vc->vc_rows;
if (logo_shown >= 0) if (logo_shown >= 0)
goto redraw_down; goto redraw_down;
switch (p->scrollmode) { switch (fb_scrollmode(p)) {
case SCROLL_MOVE: case SCROLL_MOVE:
fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
-count); -count);
...@@ -1946,12 +1948,12 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, ...@@ -1946,12 +1948,12 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy,
height, width); height, width);
} }
static void updatescrollmode(struct fbcon_display *p, static void updatescrollmode_accel(struct fbcon_display *p,
struct fb_info *info, struct fb_info *info,
struct vc_data *vc) struct vc_data *vc)
{ {
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
struct fbcon_ops *ops = info->fbcon_par; struct fbcon_ops *ops = info->fbcon_par;
int fh = vc->vc_font.height;
int cap = info->flags; int cap = info->flags;
u16 t = 0; u16 t = 0;
int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep, int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep,
...@@ -1972,12 +1974,6 @@ static void updatescrollmode(struct fbcon_display *p, ...@@ -1972,12 +1974,6 @@ static void updatescrollmode(struct fbcon_display *p,
int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) && int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) &&
!(cap & FBINFO_HWACCEL_DISABLED); !(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 (good_wrap || good_pan) {
if (reading_fast || fast_copyarea) if (reading_fast || fast_copyarea)
p->scrollmode = good_wrap ? p->scrollmode = good_wrap ?
...@@ -1991,6 +1987,27 @@ static void updatescrollmode(struct fbcon_display *p, ...@@ -1991,6 +1987,27 @@ static void updatescrollmode(struct fbcon_display *p,
else else
p->scrollmode = SCROLL_REDRAW; 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) #define PITCH(w) (((w) + 7) >> 3)
...@@ -2148,7 +2165,7 @@ static int fbcon_switch(struct vc_data *vc) ...@@ -2148,7 +2165,7 @@ static int fbcon_switch(struct vc_data *vc)
updatescrollmode(p, info, vc); updatescrollmode(p, info, vc);
switch (p->scrollmode) { switch (fb_scrollmode(p)) {
case SCROLL_WRAP_MOVE: case SCROLL_WRAP_MOVE:
scrollback_phys_max = p->vrows - vc->vc_rows; scrollback_phys_max = p->vrows - vc->vc_rows;
break; break;
......
...@@ -29,7 +29,9 @@ struct fbcon_display { ...@@ -29,7 +29,9 @@ struct fbcon_display {
/* Filled in by the low-level console driver */ /* Filled in by the low-level console driver */
const u_char *fontdata; const u_char *fontdata;
int userfont; /* != 0 if fontdata kmalloc()ed */ 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 */ u_short inverse; /* != 0 text black on white as default */
short yscroll; /* Hardware scrolling */ short yscroll; /* Hardware scrolling */
int vrows; /* number of virtual rows */ int vrows; /* number of virtual rows */
...@@ -208,6 +210,17 @@ static inline int attr_col_ec(int shift, struct vc_data *vc, ...@@ -208,6 +210,17 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
#define SCROLL_REDRAW 0x004 #define SCROLL_REDRAW 0x004
#define SCROLL_PAN_REDRAW 0x005 #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 #ifdef CONFIG_FB_TILEBLITTING
extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info); extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
#endif #endif
......
...@@ -65,7 +65,7 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, ...@@ -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 fbcon_ops *ops = info->fbcon_par;
struct fb_copyarea area; 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.sx = sy * vc->vc_font.height;
area.sy = vyres - ((sx + width) * vc->vc_font.width); 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, ...@@ -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 fbcon_ops *ops = info->fbcon_par;
struct fb_fillrect region; struct fb_fillrect region;
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; 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.color = attr_bgcol_ec(bgshift,vc,info);
region.dx = sy * vc->vc_font.height; region.dx = sy * vc->vc_font.height;
...@@ -140,7 +140,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info, ...@@ -140,7 +140,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info,
u32 cnt, pitch, size; u32 cnt, pitch, size;
u32 attribute = get_attribute(info, scr_readw(s)); u32 attribute = get_attribute(info, scr_readw(s));
u8 *dst, *buf = NULL; u8 *dst, *buf = NULL;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = GETVYRES(ops->p, info);
if (!ops->fontbuffer) if (!ops->fontbuffer)
return; return;
...@@ -229,7 +229,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, ...@@ -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 attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy; int err = 1, dx, dy;
char *src; char *src;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = GETVYRES(ops->p, info);
if (!ops->fontbuffer) if (!ops->fontbuffer)
return; return;
...@@ -387,7 +387,7 @@ static int ccw_update_start(struct fb_info *info) ...@@ -387,7 +387,7 @@ static int ccw_update_start(struct fb_info *info)
{ {
struct fbcon_ops *ops = info->fbcon_par; struct fbcon_ops *ops = info->fbcon_par;
u32 yoffset; u32 yoffset;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = GETVYRES(ops->p, info);
int err; int err;
yoffset = (vyres - info->var.yres) - ops->var.xoffset; yoffset = (vyres - info->var.yres) - ops->var.xoffset;
......
...@@ -50,7 +50,7 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, ...@@ -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 fbcon_ops *ops = info->fbcon_par;
struct fb_copyarea area; 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.sx = vxres - ((sy + height) * vc->vc_font.height);
area.sy = sx * vc->vc_font.width; 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, ...@@ -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 fbcon_ops *ops = info->fbcon_par;
struct fb_fillrect region; struct fb_fillrect region;
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; 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.color = attr_bgcol_ec(bgshift,vc,info);
region.dx = vxres - ((sy + height) * vc->vc_font.height); 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, ...@@ -125,7 +125,7 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info,
u32 cnt, pitch, size; u32 cnt, pitch, size;
u32 attribute = get_attribute(info, scr_readw(s)); u32 attribute = get_attribute(info, scr_readw(s));
u8 *dst, *buf = NULL; u8 *dst, *buf = NULL;
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = GETVXRES(ops->p, info);
if (!ops->fontbuffer) if (!ops->fontbuffer)
return; return;
...@@ -212,7 +212,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, ...@@ -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 attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy; int err = 1, dx, dy;
char *src; char *src;
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = GETVXRES(ops->p, info);
if (!ops->fontbuffer) if (!ops->fontbuffer)
return; return;
...@@ -369,7 +369,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, ...@@ -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) static int cw_update_start(struct fb_info *info)
{ {
struct fbcon_ops *ops = info->fbcon_par; struct fbcon_ops *ops = info->fbcon_par;
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = GETVXRES(ops->p, info);
u32 xoffset; u32 xoffset;
int err; int err;
......
...@@ -12,11 +12,11 @@ ...@@ -12,11 +12,11 @@
#define _FBCON_ROTATE_H #define _FBCON_ROTATE_H
#define GETVYRES(s,i) ({ \ #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; }) (i)->var.yres : (i)->var.yres_virtual; })
#define GETVXRES(s,i) ({ \ #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; }) (i)->var.xres : (i)->var.xres_virtual; })
......
...@@ -50,8 +50,8 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, ...@@ -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 fbcon_ops *ops = info->fbcon_par;
struct fb_copyarea area; struct fb_copyarea area;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = GETVYRES(ops->p, info);
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = GETVXRES(ops->p, info);
area.sy = vyres - ((sy + height) * vc->vc_font.height); area.sy = vyres - ((sy + height) * vc->vc_font.height);
area.sx = vxres - ((sx + width) * vc->vc_font.width); 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, ...@@ -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 fbcon_ops *ops = info->fbcon_par;
struct fb_fillrect region; struct fb_fillrect region;
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = GETVYRES(ops->p, info);
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = GETVXRES(ops->p, info);
region.color = attr_bgcol_ec(bgshift,vc,info); region.color = attr_bgcol_ec(bgshift,vc,info);
region.dy = vyres - ((sy + height) * vc->vc_font.height); 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, ...@@ -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 mod = vc->vc_font.width % 8, cnt, pitch, size;
u32 attribute = get_attribute(info, scr_readw(s)); u32 attribute = get_attribute(info, scr_readw(s));
u8 *dst, *buf = NULL; u8 *dst, *buf = NULL;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = GETVYRES(ops->p, info);
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = GETVXRES(ops->p, info);
if (!ops->fontbuffer) if (!ops->fontbuffer)
return; return;
...@@ -259,8 +259,8 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, ...@@ -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 attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy; int err = 1, dx, dy;
char *src; char *src;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = GETVYRES(ops->p, info);
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = GETVXRES(ops->p, info);
if (!ops->fontbuffer) if (!ops->fontbuffer)
return; return;
...@@ -410,8 +410,8 @@ static int ud_update_start(struct fb_info *info) ...@@ -410,8 +410,8 @@ static int ud_update_start(struct fb_info *info)
{ {
struct fbcon_ops *ops = info->fbcon_par; struct fbcon_ops *ops = info->fbcon_par;
int xoffset, yoffset; int xoffset, yoffset;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = GETVYRES(ops->p, info);
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = GETVXRES(ops->p, info);
int err; int err;
xoffset = vxres - info->var.xres - ops->var.xoffset; xoffset = vxres - info->var.xres - ops->var.xoffset;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment