diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-03-25 14:57:47 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-03-25 14:57:47 -0700 |
commit | cb7cbaae7fd9cee64f19cdfd89d097d807b884f5 (patch) | |
tree | e167052fd2768971c79ff7c03dd282ae9d961b02 /drivers/video | |
parent | 46f538bf2404ee9c32648deafb886f49144bfd5e (diff) | |
parent | 2a81dba4b577099717cea86d429f053e85e74d96 (diff) |
Merge tag 'drm-next-2022-03-25' of git://anongit.freedesktop.org/drm/drm
Pull drm fixes from Dave Airlie:
"Some fixes were queued up in and in light of the fbdev regressions,
I've pulled those in as well.
core:
- Make audio and color plane support checking only happen when a CEA
extension block is found.
- Small selftest fix.
fbdev:
- two regressions fixes from speedup patches.
ttm:
- Fix a small regression from ttm_resource_fini()
i915:
- Reject unsupported TMDS rates on ICL+
- Treat SAGV block time 0 as SAGV disabled
- Fix PSF GV point mask when SAGV is not possible
- Fix renamed INTEL_INFO->media.arch/ver field"
* tag 'drm-next-2022-03-25' of git://anongit.freedesktop.org/drm/drm:
fbdev: Fix cfb_imageblit() for arbitrary image widths
fbdev: Fix sys_imageblit() for arbitrary image widths
drm/edid: fix CEA extension byte #3 parsing
drm/edid: check basic audio support on CEA extension block
drm/i915: Fix renamed struct field
drm/i915: Fix PSF GV point mask when SAGV is not possible
drm/i915: Treat SAGV block time 0 as SAGV disabled
drm/i915: Reject unsupported TMDS rates on ICL+
drm/selftest: plane_helper: Put test structures in static storage
drm/ttm: Fix a kernel oops due to an invalid read
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/fbdev/core/cfbimgblt.c | 28 | ||||
-rw-r--r-- | drivers/video/fbdev/core/sysimgblt.c | 29 |
2 files changed, 49 insertions, 8 deletions
diff --git a/drivers/video/fbdev/core/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c index 7361cfabdd85..9ebda4e0dc7a 100644 --- a/drivers/video/fbdev/core/cfbimgblt.c +++ b/drivers/video/fbdev/core/cfbimgblt.c @@ -218,7 +218,7 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * { u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; u32 ppw = 32/bpp, spitch = (image->width + 7)/8; - u32 bit_mask, eorx; + u32 bit_mask, eorx, shift; const char *s = image->data, *src; u32 __iomem *dst; const u32 *tab = NULL; @@ -259,17 +259,23 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * for (i = image->height; i--; ) { dst = (u32 __iomem *)dst1; + shift = 8; src = s; + /* + * Manually unroll the per-line copying loop for better + * performance. This works until we processed the last + * completely filled source byte (inclusive). + */ switch (ppw) { case 4: /* 8 bpp */ - for (j = k; j; j -= 2, ++src) { + for (j = k; j >= 2; j -= 2, ++src) { FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++); FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++); } break; case 2: /* 16 bpp */ - for (j = k; j; j -= 4, ++src) { + for (j = k; j >= 4; j -= 4, ++src) { FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++); FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++); FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++); @@ -277,7 +283,7 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * } break; case 1: /* 32 bpp */ - for (j = k; j; j -= 8, ++src) { + for (j = k; j >= 8; j -= 8, ++src) { FB_WRITEL(colortab[(*src >> 7) & bit_mask], dst++); FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++); FB_WRITEL(colortab[(*src >> 5) & bit_mask], dst++); @@ -290,6 +296,20 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * break; } + /* + * For image widths that are not a multiple of 8, there + * are trailing pixels left on the current line. Print + * them as well. + */ + for (; j--; ) { + shift -= ppw; + FB_WRITEL(colortab[(*src >> shift) & bit_mask], dst++); + if (!shift) { + shift = 8; + ++src; + } + } + dst1 += p->fix.line_length; s += spitch; } diff --git a/drivers/video/fbdev/core/sysimgblt.c b/drivers/video/fbdev/core/sysimgblt.c index 722c327a381b..335e92b813fc 100644 --- a/drivers/video/fbdev/core/sysimgblt.c +++ b/drivers/video/fbdev/core/sysimgblt.c @@ -188,7 +188,7 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p, { u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; u32 ppw = 32/bpp, spitch = (image->width + 7)/8; - u32 bit_mask, eorx; + u32 bit_mask, eorx, shift; const char *s = image->data, *src; u32 *dst; const u32 *tab; @@ -229,17 +229,23 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p, for (i = image->height; i--; ) { dst = dst1; + shift = 8; src = s; + /* + * Manually unroll the per-line copying loop for better + * performance. This works until we processed the last + * completely filled source byte (inclusive). + */ switch (ppw) { case 4: /* 8 bpp */ - for (j = k; j; j -= 2, ++src) { + for (j = k; j >= 2; j -= 2, ++src) { *dst++ = colortab[(*src >> 4) & bit_mask]; *dst++ = colortab[(*src >> 0) & bit_mask]; } break; case 2: /* 16 bpp */ - for (j = k; j; j -= 4, ++src) { + for (j = k; j >= 4; j -= 4, ++src) { *dst++ = colortab[(*src >> 6) & bit_mask]; *dst++ = colortab[(*src >> 4) & bit_mask]; *dst++ = colortab[(*src >> 2) & bit_mask]; @@ -247,7 +253,7 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p, } break; case 1: /* 32 bpp */ - for (j = k; j; j -= 8, ++src) { + for (j = k; j >= 8; j -= 8, ++src) { *dst++ = colortab[(*src >> 7) & bit_mask]; *dst++ = colortab[(*src >> 6) & bit_mask]; *dst++ = colortab[(*src >> 5) & bit_mask]; @@ -259,6 +265,21 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p, } break; } + + /* + * For image widths that are not a multiple of 8, there + * are trailing pixels left on the current line. Print + * them as well. + */ + for (; j--; ) { + shift -= ppw; + *dst++ = colortab[(*src >> shift) & bit_mask]; + if (!shift) { + shift = 8; + ++src; + } + } + dst1 += p->fix.line_length; s += spitch; } |