aboutsummaryrefslogtreecommitdiff
path: root/drivers/video/fbdev
diff options
context:
space:
mode:
authorLinus Torvalds2022-03-24 16:19:43 -0700
committerLinus Torvalds2022-03-24 16:19:43 -0700
commitb14ffae378aa1db993e62b01392e70d1e585fb23 (patch)
tree0ac179d24e8a62ec4c2732ed18d90d83da4b82d7 /drivers/video/fbdev
parent52deda9551a01879b3562e7b41748e85c591f14c (diff)
parentc6e90a1c660874736bd09c1fec6312b4b4c2ff7b (diff)
Merge tag 'drm-next-2022-03-24' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie: "Lots of work all over, Intel improving DG2 support, amdkfd CRIU support, msm new hw support, and faster fbdev support. dma-buf: - rename dma-buf-map to iosys-map core: - move buddy allocator to core - add pci/platform init macros - improve EDID parser deep color handling - EDID timing type 7 support - add GPD Win Max quirk - add yes/no helpers to string_helpers - flatten syncobj chains - add nomodeset support to lots of drivers - improve fb-helper clipping support - add default property value interface fbdev: - improve fbdev ops speed ttm: - add a backpointer from ttm bo->ttm resource dp: - move displayport headers - add a dp helper module bridge: - anx7625 atomic support, HDCP support panel: - split out panel-lvds and lvds bindings - find panels in OF subnodes privacy: - add chromeos privacy screen support fb: - hot unplug fw fb on forced removal simpledrm: - request region instead of marking ioresource busy - add panel oreintation property udmabuf: - fix oops with 0 pages amdgpu: - power management code cleanup - Enable freesync video mode by default - RAS code cleanup - Improve VRAM access for debug using SDMA - SR-IOV rework special register access and fixes - profiling power state request ioctl - expose IP discovery via sysfs - Cyan skillfish updates - GC 10.3.7, SDMA 5.2.7, DCN 3.1.6 updates - expose benchmark tests via debugfs - add module param to disable XGMI for testing - GPU reset debugfs register dumping support amdkfd: - CRIU support - SDMA queue fixes radeon: - UVD suspend fix - iMac backlight fix i915: - minimal parallel submission for execlists - DG2-G12 subplatform added - DG2 programming workarounds - DG2 accelerated migration support - flat CCS and CCS engine support for XeHP - initial small BAR support - drop fake LMEM support - ADL-N PCH support - bigjoiner updates - introduce VMA resources and async unbinding - register definitions cleanups - multi-FBC refactoring - DG1 OPROM over SPI support - ADL-N platform enabling - opregion mailbox #5 support - DP MST ESI improvements - drm device based logging - async flip optimisation for DG2 - CPU arch abstraction fixes - improve GuC ADS init to work on aarch64 - tweak TTM LRU priority hint - GuC 69.0.3 support - remove short term execbuf pins nouveau: - higher DP/eDP bitrates - backlight fixes msm: - dpu + dp support for sc8180x - dp support for sm8350 - dpu + dsi support for qcm2290 - 10nm dsi phy tuning support - bridge support for dp encoder - gpu support for additional 7c3 SKUs ingenic: - HDMI support for JZ4780 - aux channel EDID support ast: - AST2600 support - add wide screen support - create DP/DVI connectors omapdrm: - fix implicit dma_buf fencing vc4: - add CSC + full range support - better display firmware handoff panfrost: - add initial dual-core GPU support stm: - new revision support - fb handover support mediatek: - transfer display binding document to yaml format. - add mt8195 display device binding. - allow commands to be sent during video mode. - add wait_for_event for crtc disable by cmdq. tegra: - YUV format support rcar-du: - LVDS support for M3-W+ (R8A77961) exynos: - BGR pixel format for FIMD device" * tag 'drm-next-2022-03-24' of git://anongit.freedesktop.org/drm/drm: (1529 commits) drm/i915/display: Do not re-enable PSR after it was marked as not reliable drm/i915/display: Fix HPD short pulse handling for eDP drm/amdgpu: Use drm_mode_copy() drm/radeon: Use drm_mode_copy() drm/amdgpu: Use ternary operator in `vcn_v1_0_start()` drm/amdgpu: Remove pointless on stack mode copies drm/amd/pm: fix indenting in __smu_cmn_reg_print_error() drm/amdgpu/dc: fix typos in comments drm/amdgpu: fix typos in comments drm/amd/pm: fix typos in comments drm/amdgpu: Add stolen reserved memory for MI25 SRIOV. drm/amdgpu: Merge get_reserved_allocation to get_vbios_allocations. drm/amdkfd: evict svm bo worker handle error drm/amdgpu/vcn: fix vcn ring test failure in igt reload test drm/amdgpu: only allow secure submission on rings which support that drm/amdgpu: fixed the warnings reported by kernel test robot drm/amd/display: 3.2.177 drm/amd/display: [FW Promotion] Release 0.0.108.0 drm/amd/display: Add save/restore PANEL_PWRSEQ_REF_DIV2 drm/amd/display: Wait for hubp read line for Pollock ...
Diffstat (limited to 'drivers/video/fbdev')
-rw-r--r--drivers/video/fbdev/broadsheetfb.c1
-rw-r--r--drivers/video/fbdev/core/cfbimgblt.c107
-rw-r--r--drivers/video/fbdev/core/fb_defio.c48
-rw-r--r--drivers/video/fbdev/core/fbmem.c29
-rw-r--r--drivers/video/fbdev/core/sysfillrect.c16
-rw-r--r--drivers/video/fbdev/core/sysimgblt.c49
-rw-r--r--drivers/video/fbdev/metronomefb.c1
-rw-r--r--drivers/video/fbdev/s3c-fb.c2
-rw-r--r--drivers/video/fbdev/simplefb.c65
-rw-r--r--drivers/video/fbdev/udlfb.c1
-rw-r--r--drivers/video/fbdev/vga16fb.c5
11 files changed, 224 insertions, 100 deletions
diff --git a/drivers/video/fbdev/broadsheetfb.c b/drivers/video/fbdev/broadsheetfb.c
index fd66f4d4a621..b9054f658838 100644
--- a/drivers/video/fbdev/broadsheetfb.c
+++ b/drivers/video/fbdev/broadsheetfb.c
@@ -1059,6 +1059,7 @@ static const struct fb_ops broadsheetfb_ops = {
static struct fb_deferred_io broadsheetfb_defio = {
.delay = HZ/4,
+ .sort_pagelist = true,
.deferred_io = broadsheetfb_dpy_deferred_io,
};
diff --git a/drivers/video/fbdev/core/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c
index a2bb276a8b24..7361cfabdd85 100644
--- a/drivers/video/fbdev/core/cfbimgblt.c
+++ b/drivers/video/fbdev/core/cfbimgblt.c
@@ -16,15 +16,15 @@
* must be laid out exactly in the same format as the framebuffer. Yes I know
* their are cards with hardware that coverts images of various depths to the
* framebuffer depth. But not every card has this. All images must be rounded
- * up to the nearest byte. For example a bitmap 12 bits wide must be two
- * bytes width.
+ * up to the nearest byte. For example a bitmap 12 bits wide must be two
+ * bytes width.
*
- * Tony:
- * Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds
+ * Tony:
+ * Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds
* up the code significantly.
- *
+ *
* Code for depths not multiples of BITS_PER_LONG is still kludgy, which is
- * still processed a bit at a time.
+ * still processed a bit at a time.
*
* Also need to add code to deal with cards endians that are different than
* the native cpu endians. I also need to deal with MSB position in the word.
@@ -72,8 +72,8 @@ static const u32 cfb_tab32[] = {
#define FB_WRITEL fb_writel
#define FB_READL fb_readl
-static inline void color_imageblit(const struct fb_image *image,
- struct fb_info *p, u8 __iomem *dst1,
+static inline void color_imageblit(const struct fb_image *image,
+ struct fb_info *p, u8 __iomem *dst1,
u32 start_index,
u32 pitch_index)
{
@@ -92,7 +92,7 @@ static inline void color_imageblit(const struct fb_image *image,
dst = (u32 __iomem *) dst1;
shift = 0;
val = 0;
-
+
if (start_index) {
u32 start_mask = ~fb_shifted_pixels_mask_u32(p,
start_index, bswapmask);
@@ -109,8 +109,8 @@ static inline void color_imageblit(const struct fb_image *image,
val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
if (shift >= null_bits) {
FB_WRITEL(val, dst++);
-
- val = (shift == null_bits) ? 0 :
+
+ val = (shift == null_bits) ? 0 :
FB_SHIFT_LOW(p, color, 32 - shift);
}
shift += bpp;
@@ -134,9 +134,9 @@ static inline void color_imageblit(const struct fb_image *image,
}
}
-static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p,
+static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p,
u8 __iomem *dst1, u32 fgcolor,
- u32 bgcolor,
+ u32 bgcolor,
u32 start_index,
u32 pitch_index)
{
@@ -172,7 +172,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
l--;
color = (*s & (1 << l)) ? fgcolor : bgcolor;
val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
-
+
/* Did the bitshift spill bits to the next long? */
if (shift >= null_bits) {
FB_WRITEL(val, dst++);
@@ -191,16 +191,16 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
}
-
+
dst1 += pitch;
- src += spitch;
+ src += spitch;
if (pitch_index) {
dst2 += pitch;
dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
start_index += pitch_index;
start_index &= 32 - 1;
}
-
+
}
}
@@ -212,29 +212,35 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
* fix->line_legth is divisible by 4;
* beginning and end of a scanline is dword aligned
*/
-static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p,
- u8 __iomem *dst1, u32 fgcolor,
- u32 bgcolor)
+static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p,
+ u8 __iomem *dst1, u32 fgcolor,
+ u32 bgcolor)
{
u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
- u32 bit_mask, end_mask, eorx, shift;
+ u32 bit_mask, eorx;
const char *s = image->data, *src;
u32 __iomem *dst;
const u32 *tab = NULL;
+ size_t tablen;
+ u32 colortab[16];
int i, j, k;
switch (bpp) {
case 8:
tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
+ tablen = 16;
break;
case 16:
tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
+ tablen = 4;
break;
case 32:
- default:
tab = cfb_tab32;
+ tablen = 2;
break;
+ default:
+ return;
}
for (i = ppw-1; i--; ) {
@@ -243,25 +249,52 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info *
fgx |= fgcolor;
bgx |= bgcolor;
}
-
+
bit_mask = (1 << ppw) - 1;
eorx = fgx ^ bgx;
k = image->width/ppw;
+ for (i = 0; i < tablen; ++i)
+ colortab[i] = (tab[i] & eorx) ^ bgx;
+
for (i = image->height; i--; ) {
- dst = (u32 __iomem *) dst1, shift = 8; src = s;
-
- for (j = k; j--; ) {
- shift -= ppw;
- end_mask = tab[(*src >> shift) & bit_mask];
- FB_WRITEL((end_mask & eorx)^bgx, dst++);
- if (!shift) { shift = 8; src++; }
+ dst = (u32 __iomem *)dst1;
+ src = s;
+
+ switch (ppw) {
+ case 4: /* 8 bpp */
+ for (j = k; j; 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) {
+ FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++);
+ }
+ break;
+ case 1: /* 32 bpp */
+ for (j = k; j; 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++);
+ FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 3) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 1) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++);
+ }
+ break;
}
+
dst1 += p->fix.line_length;
s += spitch;
}
-}
-
+}
+
void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
{
u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
@@ -292,13 +325,13 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
} else {
fgcolor = image->fg_color;
bgcolor = image->bg_color;
- }
-
- if (32 % bpp == 0 && !start_index && !pitch_index &&
+ }
+
+ if (32 % bpp == 0 && !start_index && !pitch_index &&
((width & (32/bpp-1)) == 0) &&
- bpp >= 8 && bpp <= 32)
+ bpp >= 8 && bpp <= 32)
fast_imageblit(image, p, dst1, fgcolor, bgcolor);
- else
+ else
slow_imageblit(image, p, dst1, fgcolor, bgcolor,
start_index, pitch_index);
} else
diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c
index d0b0b05e0dff..842c66b3e33d 100644
--- a/drivers/video/fbdev/core/fb_defio.c
+++ b/drivers/video/fbdev/core/fb_defio.c
@@ -59,6 +59,7 @@ static vm_fault_t fb_deferred_io_fault(struct vm_fault *vmf)
printk(KERN_ERR "no mapping available\n");
BUG_ON(!page->mapping);
+ INIT_LIST_HEAD(&page->lru);
page->index = vmf->pgoff;
vmf->page = page;
@@ -95,7 +96,7 @@ static vm_fault_t fb_deferred_io_mkwrite(struct vm_fault *vmf)
struct page *page = vmf->page;
struct fb_info *info = vmf->vma->vm_private_data;
struct fb_deferred_io *fbdefio = info->fbdefio;
- struct page *cur;
+ struct list_head *pos = &fbdefio->pagelist;
/* this is a callback we get when userspace first tries to
write to the page. we schedule a workqueue. that workqueue
@@ -122,21 +123,38 @@ static vm_fault_t fb_deferred_io_mkwrite(struct vm_fault *vmf)
*/
lock_page(page);
- /* we loop through the pagelist before adding in order
- to keep the pagelist sorted */
- list_for_each_entry(cur, &fbdefio->pagelist, lru) {
- /* this check is to catch the case where a new
- process could start writing to the same page
- through a new pte. this new access can cause the
- mkwrite even when the original ps's pte is marked
- writable */
- if (unlikely(cur == page))
- goto page_already_added;
- else if (cur->index > page->index)
- break;
+ /*
+ * This check is to catch the case where a new process could start
+ * writing to the same page through a new PTE. This new access
+ * can cause a call to .page_mkwrite even if the original process'
+ * PTE is marked writable.
+ *
+ * TODO: The lru field is owned by the page cache; hence the name.
+ * We dequeue in fb_deferred_io_work() after flushing the
+ * page's content into video memory. Instead of lru, fbdefio
+ * should have it's own field.
+ */
+ if (!list_empty(&page->lru))
+ goto page_already_added;
+
+ if (unlikely(fbdefio->sort_pagelist)) {
+ /*
+ * We loop through the pagelist before adding in order to
+ * keep the pagelist sorted. This has significant overhead
+ * of O(n^2) with n being the number of written pages. If
+ * possible, drivers should try to work with unsorted page
+ * lists instead.
+ */
+ struct page *cur;
+
+ list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+ if (cur->index > page->index)
+ break;
+ }
+ pos = &cur->lru;
}
- list_add_tail(&page->lru, &cur->lru);
+ list_add_tail(&page->lru, pos);
page_already_added:
mutex_unlock(&fbdefio->lock);
@@ -187,7 +205,7 @@ static void fb_deferred_io_work(struct work_struct *work)
/* clear the list */
list_for_each_safe(node, next, &fbdefio->pagelist) {
- list_del(node);
+ list_del_init(node);
}
mutex_unlock(&fbdefio->lock);
}
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 8df3ac991e5a..34d6bb1bf82e 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -25,6 +25,7 @@
#include <linux/init.h>
#include <linux/linux_logo.h>
#include <linux/proc_fs.h>
+#include <linux/platform_device.h>
#include <linux/seq_file.h>
#include <linux/console.h>
#include <linux/kmod.h>
@@ -1555,18 +1556,36 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
/* check all firmware fbs and kick off if the base addr overlaps */
for_each_registered_fb(i) {
struct apertures_struct *gen_aper;
+ struct device *device;
if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
continue;
gen_aper = registered_fb[i]->apertures;
+ device = registered_fb[i]->device;
if (fb_do_apertures_overlap(gen_aper, a) ||
(primary && gen_aper && gen_aper->count &&
gen_aper->ranges[0].base == VGA_FB_PHYS)) {
printk(KERN_INFO "fb%d: switching to %s from %s\n",
i, name, registered_fb[i]->fix.id);
- do_unregister_framebuffer(registered_fb[i]);
+
+ /*
+ * If we kick-out a firmware driver, we also want to remove
+ * the underlying platform device, such as simple-framebuffer,
+ * VESA, EFI, etc. A native driver will then be able to
+ * allocate the memory range.
+ *
+ * If it's not a platform device, at least print a warning. A
+ * fix would add code to remove the device from the system.
+ */
+ if (dev_is_platform(device)) {
+ registered_fb[i]->forced_out = true;
+ platform_device_unregister(to_platform_device(device));
+ } else {
+ pr_warn("fb%d: cannot remove device\n", i);
+ do_unregister_framebuffer(registered_fb[i]);
+ }
}
}
}
@@ -1896,9 +1915,13 @@ EXPORT_SYMBOL(register_framebuffer);
void
unregister_framebuffer(struct fb_info *fb_info)
{
- mutex_lock(&registration_lock);
+ bool forced_out = fb_info->forced_out;
+
+ if (!forced_out)
+ mutex_lock(&registration_lock);
do_unregister_framebuffer(fb_info);
- mutex_unlock(&registration_lock);
+ if (!forced_out)
+ mutex_unlock(&registration_lock);
}
EXPORT_SYMBOL(unregister_framebuffer);
diff --git a/drivers/video/fbdev/core/sysfillrect.c b/drivers/video/fbdev/core/sysfillrect.c
index 33ee3d34f9d2..bcdcaeae6538 100644
--- a/drivers/video/fbdev/core/sysfillrect.c
+++ b/drivers/video/fbdev/core/sysfillrect.c
@@ -50,19 +50,9 @@ bitfill_aligned(struct fb_info *p, unsigned long *dst, int dst_idx,
/* Main chunk */
n /= bits;
- while (n >= 8) {
- *dst++ = pat;
- *dst++ = pat;
- *dst++ = pat;
- *dst++ = pat;
- *dst++ = pat;
- *dst++ = pat;
- *dst++ = pat;
- *dst++ = pat;
- n -= 8;
- }
- while (n--)
- *dst++ = pat;
+ memset_l(dst, pat, n);
+ dst += n;
+
/* Trailing bits */
if (last)
*dst = comp(pat, *dst, last);
diff --git a/drivers/video/fbdev/core/sysimgblt.c b/drivers/video/fbdev/core/sysimgblt.c
index a4d05b1b17d7..722c327a381b 100644
--- a/drivers/video/fbdev/core/sysimgblt.c
+++ b/drivers/video/fbdev/core/sysimgblt.c
@@ -188,23 +188,29 @@ 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, end_mask, eorx, shift;
+ u32 bit_mask, eorx;
const char *s = image->data, *src;
u32 *dst;
- const u32 *tab = NULL;
+ const u32 *tab;
+ size_t tablen;
+ u32 colortab[16];
int i, j, k;
switch (bpp) {
case 8:
tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
+ tablen = 16;
break;
case 16:
tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
+ tablen = 4;
break;
case 32:
- default:
tab = cfb_tab32;
+ tablen = 2;
break;
+ default:
+ return;
}
for (i = ppw-1; i--; ) {
@@ -218,19 +224,40 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
eorx = fgx ^ bgx;
k = image->width/ppw;
+ for (i = 0; i < tablen; ++i)
+ colortab[i] = (tab[i] & eorx) ^ bgx;
+
for (i = image->height; i--; ) {
dst = dst1;
- shift = 8;
src = s;
- for (j = k; j--; ) {
- shift -= ppw;
- end_mask = tab[(*src >> shift) & bit_mask];
- *dst++ = (end_mask & eorx) ^ bgx;
- if (!shift) {
- shift = 8;
- src++;
+ switch (ppw) {
+ case 4: /* 8 bpp */
+ for (j = k; j; 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) {
+ *dst++ = colortab[(*src >> 6) & bit_mask];
+ *dst++ = colortab[(*src >> 4) & bit_mask];
+ *dst++ = colortab[(*src >> 2) & bit_mask];
+ *dst++ = colortab[(*src >> 0) & bit_mask];
+ }
+ break;
+ case 1: /* 32 bpp */
+ for (j = k; j; j -= 8, ++src) {
+ *dst++ = colortab[(*src >> 7) & bit_mask];
+ *dst++ = colortab[(*src >> 6) & bit_mask];
+ *dst++ = colortab[(*src >> 5) & bit_mask];
+ *dst++ = colortab[(*src >> 4) & bit_mask];
+ *dst++ = colortab[(*src >> 3) & bit_mask];
+ *dst++ = colortab[(*src >> 2) & bit_mask];
+ *dst++ = colortab[(*src >> 1) & bit_mask];
+ *dst++ = colortab[(*src >> 0) & bit_mask];
}
+ break;
}
dst1 += p->fix.line_length;
s += spitch;
diff --git a/drivers/video/fbdev/metronomefb.c b/drivers/video/fbdev/metronomefb.c
index 952826557a0c..af858dd23ea6 100644
--- a/drivers/video/fbdev/metronomefb.c
+++ b/drivers/video/fbdev/metronomefb.c
@@ -568,6 +568,7 @@ static const struct fb_ops metronomefb_ops = {
static struct fb_deferred_io metronomefb_defio = {
.delay = HZ,
+ .sort_pagelist = true,
.deferred_io = metronomefb_dpy_deferred_io,
};
diff --git a/drivers/video/fbdev/s3c-fb.c b/drivers/video/fbdev/s3c-fb.c
index fe3c8b6935cf..3abbc5737c3b 100644
--- a/drivers/video/fbdev/s3c-fb.c
+++ b/drivers/video/fbdev/s3c-fb.c
@@ -489,7 +489,7 @@ static int s3c_fb_set_par(struct fb_info *info)
struct s3c_fb_win *win = info->par;
struct s3c_fb *sfb = win->parent;
void __iomem *regs = sfb->regs;
- void __iomem *buf = regs;
+ void __iomem *buf;
int win_no = win->index;
u32 alpha = 0;
u32 data;
diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c
index 57541887188b..94fc9c6d0411 100644
--- a/drivers/video/fbdev/simplefb.c
+++ b/drivers/video/fbdev/simplefb.c
@@ -66,16 +66,36 @@ static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
return 0;
}
-struct simplefb_par;
+struct simplefb_par {
+ u32 palette[PSEUDO_PALETTE_SIZE];
+ struct resource *mem;
+#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
+ bool clks_enabled;
+ unsigned int clk_count;
+ struct clk **clks;
+#endif
+#if defined CONFIG_OF && defined CONFIG_REGULATOR
+ bool regulators_enabled;
+ u32 regulator_count;
+ struct regulator **regulators;
+#endif
+};
+
static void simplefb_clocks_destroy(struct simplefb_par *par);
static void simplefb_regulators_destroy(struct simplefb_par *par);
static void simplefb_destroy(struct fb_info *info)
{
+ struct simplefb_par *par = info->par;
+ struct resource *mem = par->mem;
+
simplefb_regulators_destroy(info->par);
simplefb_clocks_destroy(info->par);
if (info->screen_base)
iounmap(info->screen_base);
+
+ if (mem)
+ release_mem_region(mem->start, resource_size(mem));
}
static const struct fb_ops simplefb_ops = {
@@ -169,20 +189,6 @@ static int simplefb_parse_pd(struct platform_device *pdev,
return 0;
}
-struct simplefb_par {
- u32 palette[PSEUDO_PALETTE_SIZE];
-#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
- bool clks_enabled;
- unsigned int clk_count;
- struct clk **clks;
-#endif
-#if defined CONFIG_OF && defined CONFIG_REGULATOR
- bool regulators_enabled;
- u32 regulator_count;
- struct regulator **regulators;
-#endif
-};
-
#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
/*
* Clock handling code.
@@ -405,7 +411,7 @@ static int simplefb_probe(struct platform_device *pdev)
struct simplefb_params params;
struct fb_info *info;
struct simplefb_par *par;
- struct resource *mem;
+ struct resource *res, *mem;
/*
* Generic drivers must not be registered if a framebuffer exists.
@@ -430,15 +436,28 @@ static int simplefb_probe(struct platform_device *pdev)
if (ret)
return ret;
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
dev_err(&pdev->dev, "No memory resource\n");
return -EINVAL;
}
+ mem = request_mem_region(res->start, resource_size(res), "simplefb");
+ if (!mem) {
+ /*
+ * We cannot make this fatal. Sometimes this comes from magic
+ * spaces our resource handlers simply don't know about. Use
+ * the I/O-memory resource as-is and try to map that instead.
+ */
+ dev_warn(&pdev->dev, "simplefb: cannot reserve video memory at %pR\n", res);
+ mem = res;
+ }
+
info = framebuffer_alloc(sizeof(struct simplefb_par), &pdev->dev);
- if (!info)
- return -ENOMEM;
+ if (!info) {
+ ret = -ENOMEM;
+ goto error_release_mem_region;
+ }
platform_set_drvdata(pdev, info);
par = info->par;
@@ -495,6 +514,9 @@ static int simplefb_probe(struct platform_device *pdev)
info->var.xres, info->var.yres,
info->var.bits_per_pixel, info->fix.line_length);
+ if (mem != res)
+ par->mem = mem; /* release in clean-up handler */
+
ret = register_framebuffer(info);
if (ret < 0) {
dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);
@@ -513,6 +535,9 @@ error_unmap:
iounmap(info->screen_base);
error_fb_release:
framebuffer_release(info);
+error_release_mem_region:
+ if (mem != res)
+ release_mem_region(mem->start, resource_size(mem));
return ret;
}
diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c
index 90f48b71fd8f..b6ec0b8e2b72 100644
--- a/drivers/video/fbdev/udlfb.c
+++ b/drivers/video/fbdev/udlfb.c
@@ -980,6 +980,7 @@ static int dlfb_ops_open(struct fb_info *info, int user)
if (fbdefio) {
fbdefio->delay = DL_DEFIO_WRITE_DELAY;
+ fbdefio->sort_pagelist = true;
fbdefio->deferred_io = dlfb_dpy_deferred_io;
}
diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c
index 96e312a3eac7..d21f68f3ee44 100644
--- a/drivers/video/fbdev/vga16fb.c
+++ b/drivers/video/fbdev/vga16fb.c
@@ -1351,7 +1351,12 @@ static int vga16fb_probe(struct platform_device *dev)
printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
par = info->par;
+#if defined(CONFIG_X86)
+ par->isVGA = screen_info.orig_video_isVGA == VIDEO_TYPE_VGAC;
+#else
+ /* non-x86 architectures treat orig_video_isVGA as a boolean flag */
par->isVGA = screen_info.orig_video_isVGA;
+#endif
par->palette_blanked = 0;
par->vesa_blanked = 0;