From 23fa18eaa71266feff7ba8d83022d9e1cc83c65a Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 07:42:03 +0000
Subject: [PATCH] disable pwm7
---
kernel/drivers/video/fbdev/core/fbmem.c | 687 +++++++++++++++++++++++++++------------------------------
1 files changed, 326 insertions(+), 361 deletions(-)
diff --git a/kernel/drivers/video/fbdev/core/fbmem.c b/kernel/drivers/video/fbdev/core/fbmem.c
index 036f96c..1704dea 100644
--- a/kernel/drivers/video/fbdev/core/fbmem.c
+++ b/kernel/drivers/video/fbdev/core/fbmem.c
@@ -28,13 +28,13 @@
#include <linux/seq_file.h>
#include <linux/console.h>
#include <linux/kmod.h>
-#include <linux/dma-buf.h>
#include <linux/err.h>
#include <linux/device.h>
#include <linux/efi.h>
#include <linux/fb.h>
#include <linux/fbcon.h>
#include <linux/mem_encrypt.h>
+#include <linux/pci.h>
#include <asm/fb.h>
@@ -52,6 +52,10 @@
int num_registered_fb __read_mostly;
EXPORT_SYMBOL(num_registered_fb);
+
+bool fb_center_logo __read_mostly;
+
+int fb_logo_count __read_mostly = -1;
static struct fb_info *get_fb_info(unsigned int idx)
{
@@ -76,17 +80,6 @@
if (fb_info->fbops->fb_destroy)
fb_info->fbops->fb_destroy(fb_info);
}
-
-int lock_fb_info(struct fb_info *info)
-{
- mutex_lock(&info->lock);
- if (!info->fbops) {
- mutex_unlock(&info->lock);
- return 0;
- }
- return 1;
-}
-EXPORT_SYMBOL(lock_fb_info);
/*
* Helpers
@@ -509,8 +502,24 @@
fb_set_logo(info, logo, logo_new, fb_logo.depth);
}
- image.dx = 0;
- image.dy = y;
+ if (fb_center_logo) {
+ int xres = info->var.xres;
+ int yres = info->var.yres;
+
+ if (rotate == FB_ROTATE_CW || rotate == FB_ROTATE_CCW) {
+ xres = info->var.yres;
+ yres = info->var.xres;
+ }
+
+ while (n && (n * (logo->width + 8) - 8 > xres))
+ --n;
+ image.dx = (xres - (n * (logo->width + 8) - 8)) / 2;
+ image.dy = y ?: (yres - logo->height) / 2;
+ } else {
+ image.dx = 0;
+ image.dy = y;
+ }
+
image.width = logo->width;
image.height = logo->height;
@@ -528,7 +537,7 @@
info->pseudo_palette = saved_pseudo_palette;
kfree(logo_new);
kfree(logo_rotate);
- return logo->height;
+ return image.dy + logo->height;
}
@@ -580,8 +589,8 @@
unsigned int i;
for (i = 0; i < fb_logo_ex_num; i++)
- y += fb_show_logo_line(info, rotate,
- fb_logo_ex[i].logo, y, fb_logo_ex[i].n);
+ y = fb_show_logo_line(info, rotate,
+ fb_logo_ex[i].logo, y, fb_logo_ex[i].n);
return y;
}
@@ -607,11 +616,12 @@
{
int depth = fb_get_color_depth(&info->var, &info->fix);
unsigned int yres;
+ int height;
memset(&fb_logo, 0, sizeof(struct logo_data));
if (info->flags & FBINFO_MISC_TILEBLITTING ||
- info->fbops->owner)
+ info->fbops->owner || !fb_logo_count)
return 0;
if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -653,30 +663,38 @@
fb_logo.depth = 1;
- if (fb_logo.depth > 4 && depth > 4) {
- switch (info->fix.visual) {
- case FB_VISUAL_TRUECOLOR:
- fb_logo.needs_truepalette = 1;
- break;
- case FB_VISUAL_DIRECTCOLOR:
- fb_logo.needs_directpalette = 1;
- fb_logo.needs_cmapreset = 1;
- break;
- case FB_VISUAL_PSEUDOCOLOR:
- fb_logo.needs_cmapreset = 1;
- break;
- }
- }
+ if (fb_logo.depth > 4 && depth > 4) {
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ fb_logo.needs_truepalette = 1;
+ break;
+ case FB_VISUAL_DIRECTCOLOR:
+ fb_logo.needs_directpalette = 1;
+ fb_logo.needs_cmapreset = 1;
+ break;
+ case FB_VISUAL_PSEUDOCOLOR:
+ fb_logo.needs_cmapreset = 1;
+ break;
+ }
+ }
- return fb_prepare_extra_logos(info, fb_logo.logo->height, yres);
+ height = fb_logo.logo->height;
+ if (fb_center_logo)
+ height += (yres - fb_logo.logo->height) / 2;
+
+ return fb_prepare_extra_logos(info, height, yres);
}
int fb_show_logo(struct fb_info *info, int rotate)
{
+ unsigned int count;
int y;
- y = fb_show_logo_line(info, rotate, fb_logo.logo, 0,
- num_online_cpus());
+ if (!fb_logo_count)
+ return 0;
+
+ count = fb_logo_count < 0 ? num_online_cpus() : fb_logo_count;
+ y = fb_show_logo_line(info, rotate, fb_logo.logo, 0, count);
y = fb_show_extra_logos(info, y, rotate);
return y;
@@ -759,7 +777,7 @@
if (info->fbops->fb_read)
return info->fbops->fb_read(info, buf, count, ppos);
-
+
total_size = info->screen_size;
if (total_size == 0)
@@ -824,7 +842,7 @@
if (info->fbops->fb_write)
return info->fbops->fb_write(info, buf, count, ppos);
-
+
total_size = info->screen_size;
if (total_size == 0)
@@ -919,16 +937,13 @@
static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
u32 activate)
{
- struct fb_event event;
struct fb_blit_caps caps, fbcaps;
int err = 0;
memset(&caps, 0, sizeof(caps));
memset(&fbcaps, 0, sizeof(fbcaps));
caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0;
- event.info = info;
- event.data = ∩︀
- fb_notifier_call_chain(FB_EVENT_GET_REQ, &event);
+ fbcon_get_requirement(info, &caps);
info->fbops->fb_get_caps(info, &fbcaps, var);
if (((fbcaps.x ^ caps.x) & caps.x) ||
@@ -942,8 +957,12 @@
int
fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
{
- int flags = info->flags;
int ret = 0;
+ u32 activate;
+ struct fb_var_screeninfo old_var;
+ struct fb_videomode mode;
+ struct fb_event event;
+ u32 unused;
if (var->activate & FB_ACTIVATE_INV_MODE) {
struct fb_videomode mode1, mode2;
@@ -952,182 +971,144 @@
fb_var_to_videomode(&mode2, &info->var);
/* make sure we don't delete the videomode of current var */
ret = fb_mode_is_equal(&mode1, &mode2);
-
if (!ret) {
- struct fb_event event;
-
- event.info = info;
- event.data = &mode1;
- ret = fb_notifier_call_chain(FB_EVENT_MODE_DELETE, &event);
+ ret = fbcon_mode_deleted(info, &mode1);
+ if (!ret)
+ fb_delete_videomode(&mode1, &info->modelist);
}
- if (!ret)
- fb_delete_videomode(&mode1, &info->modelist);
-
-
- ret = (ret) ? -EINVAL : 0;
- goto done;
+ return ret ? -EINVAL : 0;
}
- if ((var->activate & FB_ACTIVATE_FORCE) ||
- memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
- u32 activate = var->activate;
- u32 unused;
+ if (!(var->activate & FB_ACTIVATE_FORCE) &&
+ !memcmp(&info->var, var, sizeof(struct fb_var_screeninfo)))
+ return 0;
- /* When using FOURCC mode, make sure the red, green, blue and
- * transp fields are set to 0.
- */
- if ((info->fix.capabilities & FB_CAP_FOURCC) &&
- var->grayscale > 1) {
- if (var->red.offset || var->green.offset ||
- var->blue.offset || var->transp.offset ||
- var->red.length || var->green.length ||
- var->blue.length || var->transp.length ||
- var->red.msb_right || var->green.msb_right ||
- var->blue.msb_right || var->transp.msb_right)
- return -EINVAL;
- }
+ activate = var->activate;
- if (!info->fbops->fb_check_var) {
- *var = info->var;
- goto done;
- }
-
- /* bitfill_aligned() assumes that it's at least 8x8 */
- if (var->xres < 8 || var->yres < 8)
+ /* When using FOURCC mode, make sure the red, green, blue and
+ * transp fields are set to 0.
+ */
+ if ((info->fix.capabilities & FB_CAP_FOURCC) &&
+ var->grayscale > 1) {
+ if (var->red.offset || var->green.offset ||
+ var->blue.offset || var->transp.offset ||
+ var->red.length || var->green.length ||
+ var->blue.length || var->transp.length ||
+ var->red.msb_right || var->green.msb_right ||
+ var->blue.msb_right || var->transp.msb_right)
return -EINVAL;
+ }
- /* Too huge resolution causes multiplication overflow. */
- if (check_mul_overflow(var->xres, var->yres, &unused) ||
- check_mul_overflow(var->xres_virtual, var->yres_virtual, &unused))
- return -EINVAL;
+ if (!info->fbops->fb_check_var) {
+ *var = info->var;
+ return 0;
+ }
- ret = info->fbops->fb_check_var(var, info);
+ /* bitfill_aligned() assumes that it's at least 8x8 */
+ if (var->xres < 8 || var->yres < 8)
+ return -EINVAL;
+
+ /* Too huge resolution causes multiplication overflow. */
+ if (check_mul_overflow(var->xres, var->yres, &unused) ||
+ check_mul_overflow(var->xres_virtual, var->yres_virtual, &unused))
+ return -EINVAL;
+
+ ret = info->fbops->fb_check_var(var, info);
+
+ if (ret)
+ return ret;
+
+ /* verify that virtual resolution >= physical resolution */
+ if (var->xres_virtual < var->xres ||
+ var->yres_virtual < var->yres) {
+ pr_warn("WARNING: fbcon: Driver '%s' missed to adjust virtual screen size (%ux%u vs. %ux%u)\n",
+ info->fix.id,
+ var->xres_virtual, var->yres_virtual,
+ var->xres, var->yres);
+ return -EINVAL;
+ }
+
+ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
+ return 0;
+
+ if (info->fbops->fb_get_caps) {
+ ret = fb_check_caps(info, var, activate);
if (ret)
- goto done;
+ return ret;
+ }
- if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
- struct fb_var_screeninfo old_var;
- struct fb_videomode mode;
+ old_var = info->var;
+ info->var = *var;
- if (info->fbops->fb_get_caps) {
- ret = fb_check_caps(info, var, activate);
+ if (info->fbops->fb_set_par) {
+ ret = info->fbops->fb_set_par(info);
- if (ret)
- goto done;
- }
-
- old_var = info->var;
- info->var = *var;
-
- if (info->fbops->fb_set_par) {
- ret = info->fbops->fb_set_par(info);
-
- if (ret) {
- info->var = old_var;
- printk(KERN_WARNING "detected "
- "fb_set_par error, "
- "error code: %d\n", ret);
- goto done;
- }
- }
-
- fb_pan_display(info, &info->var);
- fb_set_cmap(&info->cmap, info);
- fb_var_to_videomode(&mode, &info->var);
-
- if (info->modelist.prev && info->modelist.next &&
- !list_empty(&info->modelist))
- ret = fb_add_videomode(&mode, &info->modelist);
-
- if (!ret && (flags & FBINFO_MISC_USEREVENT)) {
- struct fb_event event;
- int evnt = (activate & FB_ACTIVATE_ALL) ?
- FB_EVENT_MODE_CHANGE_ALL :
- FB_EVENT_MODE_CHANGE;
-
- info->flags &= ~FBINFO_MISC_USEREVENT;
- event.info = info;
- event.data = &mode;
- fb_notifier_call_chain(evnt, &event);
- }
+ if (ret) {
+ info->var = old_var;
+ printk(KERN_WARNING "detected "
+ "fb_set_par error, "
+ "error code: %d\n", ret);
+ return ret;
}
}
- done:
- return ret;
+ fb_pan_display(info, &info->var);
+ fb_set_cmap(&info->cmap, info);
+ fb_var_to_videomode(&mode, &info->var);
+
+ if (info->modelist.prev && info->modelist.next &&
+ !list_empty(&info->modelist))
+ ret = fb_add_videomode(&mode, &info->modelist);
+
+ if (ret)
+ return ret;
+
+ event.info = info;
+ event.data = &mode;
+ fb_notifier_call_chain(FB_EVENT_MODE_CHANGE, &event);
+
+ return 0;
}
EXPORT_SYMBOL(fb_set_var);
int
fb_blank(struct fb_info *info, int blank)
-{
+{
struct fb_event event;
- int ret = -EINVAL, early_ret;
+ int ret = -EINVAL;
- if (blank > FB_BLANK_POWERDOWN)
- blank = FB_BLANK_POWERDOWN;
+ if (blank > FB_BLANK_POWERDOWN)
+ blank = FB_BLANK_POWERDOWN;
event.info = info;
event.data = ␣
- early_ret = fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event);
-
if (info->fbops->fb_blank)
- ret = info->fbops->fb_blank(blank, info);
+ ret = info->fbops->fb_blank(blank, info);
if (!ret)
fb_notifier_call_chain(FB_EVENT_BLANK, &event);
- else {
- /*
- * if fb_blank is failed then revert effects of
- * the early blank event.
- */
- if (!early_ret)
- fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK, &event);
- }
- return ret;
+ return ret;
}
EXPORT_SYMBOL(fb_blank);
-
-static int fb_get_dmabuf(struct fb_info *info, int flags)
-{
-#ifdef CONFIG_DMA_SHARED_BUFFER
- struct dma_buf *dmabuf;
-
- if (!info->fbops->fb_dmabuf_export)
- return -ENOTTY;
-
- dmabuf = info->fbops->fb_dmabuf_export(info);
- if (IS_ERR(dmabuf))
- return PTR_ERR(dmabuf);
-
- return dma_buf_fd(dmabuf, flags);
-#else
- return -ENOTTY;
-#endif
-}
static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
- struct fb_ops *fb;
+ const struct fb_ops *fb;
struct fb_var_screeninfo var;
struct fb_fix_screeninfo fix;
- struct fb_con2fbmap con2fb;
struct fb_cmap cmap_from;
struct fb_cmap_user cmap;
- struct fb_event event;
- struct fb_dmabuf_export dmaexp;
void __user *argp = (void __user *)arg;
long ret = 0;
switch (cmd) {
case FBIOGET_VSCREENINFO:
- if (!lock_fb_info(info))
- return -ENODEV;
+ lock_fb_info(info);
var = info->var;
unlock_fb_info(info);
@@ -1136,23 +1117,25 @@
case FBIOPUT_VSCREENINFO:
if (copy_from_user(&var, argp, sizeof(var)))
return -EFAULT;
+ /* only for kernel-internal use */
+ var.activate &= ~FB_ACTIVATE_KD_TEXT;
console_lock();
- if (!lock_fb_info(info)) {
- console_unlock();
- return -ENODEV;
- }
- info->flags |= FBINFO_MISC_USEREVENT;
- ret = fb_set_var(info, &var);
- info->flags &= ~FBINFO_MISC_USEREVENT;
+ lock_fb_info(info);
+ ret = fbcon_modechange_possible(info, &var);
+ if (!ret)
+ ret = fb_set_var(info, &var);
+ if (!ret)
+ fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
unlock_fb_info(info);
console_unlock();
if (!ret && copy_to_user(argp, &var, sizeof(var)))
ret = -EFAULT;
break;
case FBIOGET_FSCREENINFO:
- if (!lock_fb_info(info))
- return -ENODEV;
+ lock_fb_info(info);
memcpy(&fix, &info->fix, sizeof(fix));
+ if (info->flags & FBINFO_HIDE_SMEM_START)
+ fix.smem_start = 0;
unlock_fb_info(info);
ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
@@ -1165,8 +1148,7 @@
case FBIOGETCMAP:
if (copy_from_user(&cmap, argp, sizeof(cmap)))
return -EFAULT;
- if (!lock_fb_info(info))
- return -ENODEV;
+ lock_fb_info(info);
cmap_from = info->cmap;
unlock_fb_info(info);
ret = fb_cmap_to_user(&cmap_from, &cmap);
@@ -1175,10 +1157,7 @@
if (copy_from_user(&var, argp, sizeof(var)))
return -EFAULT;
console_lock();
- if (!lock_fb_info(info)) {
- console_unlock();
- return -ENODEV;
- }
+ lock_fb_info(info);
ret = fb_pan_display(info, &var);
unlock_fb_info(info);
console_unlock();
@@ -1189,73 +1168,22 @@
ret = -EINVAL;
break;
case FBIOGET_CON2FBMAP:
- if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
- return -EFAULT;
- if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
- return -EINVAL;
- con2fb.framebuffer = -1;
- event.data = &con2fb;
- if (!lock_fb_info(info))
- return -ENODEV;
- event.info = info;
- fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
- unlock_fb_info(info);
- ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;
+ ret = fbcon_get_con2fb_map_ioctl(argp);
break;
case FBIOPUT_CON2FBMAP:
- if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
- return -EFAULT;
- if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
- return -EINVAL;
- if (con2fb.framebuffer >= FB_MAX)
- return -EINVAL;
- if (!registered_fb[con2fb.framebuffer])
- request_module("fb%d", con2fb.framebuffer);
- if (!registered_fb[con2fb.framebuffer]) {
- ret = -EINVAL;
- break;
- }
- event.data = &con2fb;
- console_lock();
- if (!lock_fb_info(info)) {
- console_unlock();
- return -ENODEV;
- }
- event.info = info;
- ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event);
- unlock_fb_info(info);
- console_unlock();
+ ret = fbcon_set_con2fb_map_ioctl(argp);
break;
case FBIOBLANK:
console_lock();
- if (!lock_fb_info(info)) {
- console_unlock();
- return -ENODEV;
- }
- info->flags |= FBINFO_MISC_USEREVENT;
+ lock_fb_info(info);
ret = fb_blank(info, arg);
- info->flags &= ~FBINFO_MISC_USEREVENT;
+ /* might again call into fb_blank */
+ fbcon_fb_blanked(info, arg);
unlock_fb_info(info);
console_unlock();
break;
- case FBIOGET_DMABUF:
- if (copy_from_user(&dmaexp, argp, sizeof(dmaexp)))
- return -EFAULT;
-
- if (!lock_fb_info(info))
- return -ENODEV;
- ret = fb_get_dmabuf(info, dmaexp.flags);
- unlock_fb_info(info);
-
- if (ret < 0)
- return ret;
- dmaexp.fd = ret;
-
- ret = copy_to_user(argp, &dmaexp, sizeof(dmaexp)) ? -EFAULT : 0;
- break;
default:
- if (!lock_fb_info(info))
- return -ENODEV;
+ lock_fb_info(info);
fb = info->fbops;
if (fb->fb_ioctl)
ret = fb->fb_ioctl(info, cmd, arg);
@@ -1375,9 +1303,10 @@
{
struct fb_fix_screeninfo fix;
- if (!lock_fb_info(info))
- return -ENODEV;
+ lock_fb_info(info);
fix = info->fix;
+ if (info->flags & FBINFO_HIDE_SMEM_START)
+ fix.smem_start = 0;
unlock_fb_info(info);
return do_fscreeninfo_to_user(&fix, compat_ptr(arg));
}
@@ -1386,7 +1315,7 @@
unsigned long arg)
{
struct fb_info *info = file_fb_info(file);
- struct fb_ops *fb;
+ const struct fb_ops *fb;
long ret = -ENOIOCTLCMD;
if (!info)
@@ -1398,9 +1327,8 @@
case FBIOPAN_DISPLAY:
case FBIOGET_CON2FBMAP:
case FBIOPUT_CON2FBMAP:
- case FBIOGET_DMABUF:
arg = (unsigned long) compat_ptr(arg);
- /* fall through */
+ fallthrough;
case FBIOBLANK:
ret = do_fb_ioctl(info, cmd, arg);
break;
@@ -1427,18 +1355,23 @@
fb_mmap(struct file *file, struct vm_area_struct * vma)
{
struct fb_info *info = file_fb_info(file);
- struct fb_ops *fb;
+ int (*fb_mmap_fn)(struct fb_info *info, struct vm_area_struct *vma);
unsigned long mmio_pgoff;
unsigned long start;
u32 len;
if (!info)
return -ENODEV;
- fb = info->fbops;
- if (!fb)
- return -ENODEV;
mutex_lock(&info->mm_lock);
- if (fb->fb_mmap) {
+
+ fb_mmap_fn = info->fbops->fb_mmap;
+
+#if IS_ENABLED(CONFIG_FB_DEFERRED_IO)
+ if (info->fbdefio)
+ fb_mmap_fn = fb_deferred_io_mmap;
+#endif
+
+ if (fb_mmap_fn) {
int res;
/*
@@ -1446,7 +1379,7 @@
* SME protection is removed ahead of the call
*/
vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
- res = fb->fb_mmap(info, vma);
+ res = fb_mmap_fn(info, vma);
mutex_unlock(&info->mm_lock);
return res;
}
@@ -1500,7 +1433,7 @@
if (IS_ERR(info))
return PTR_ERR(info);
- mutex_lock(&info->lock);
+ lock_fb_info(info);
if (!try_module_get(info->fbops->owner)) {
res = -ENODEV;
goto out;
@@ -1516,24 +1449,24 @@
fb_deferred_io_open(info, inode, file);
#endif
out:
- mutex_unlock(&info->lock);
+ unlock_fb_info(info);
if (res)
put_fb_info(info);
return res;
}
-static int
+static int
fb_release(struct inode *inode, struct file *file)
__acquires(&info->lock)
__releases(&info->lock)
{
struct fb_info * const info = file->private_data;
- mutex_lock(&info->lock);
+ lock_fb_info(info);
if (info->fbops->fb_release)
info->fbops->fb_release(info,1);
module_put(info->fbops->owner);
- mutex_unlock(&info->lock);
+ unlock_fb_info(info);
put_fb_info(info);
return 0;
}
@@ -1638,13 +1571,13 @@
return false;
}
-static int do_unregister_framebuffer(struct fb_info *fb_info);
+static void do_unregister_framebuffer(struct fb_info *fb_info);
#define VGA_FB_PHYS 0xA0000
-static int do_remove_conflicting_framebuffers(struct apertures_struct *a,
- const char *name, bool primary)
+static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
+ const char *name, bool primary)
{
- int i, ret;
+ int i;
/* check all firmware fbs and kick off if the base addr overlaps */
for_each_registered_fb(i) {
@@ -1658,15 +1591,11 @@
(primary && gen_aper && gen_aper->count &&
gen_aper->ranges[0].base == VGA_FB_PHYS)) {
- printk(KERN_INFO "fb: switching to %s from %s\n",
- name, registered_fb[i]->fix.id);
- ret = do_unregister_framebuffer(registered_fb[i]);
- if (ret)
- return ret;
+ printk(KERN_INFO "fb%d: switching to %s from %s\n",
+ i, name, registered_fb[i]->fix.id);
+ do_unregister_framebuffer(registered_fb[i]);
}
}
-
- return 0;
}
static bool lockless_register_fb;
@@ -1677,17 +1606,14 @@
static int do_register_framebuffer(struct fb_info *fb_info)
{
int i, ret;
- struct fb_event event;
struct fb_videomode mode;
if (fb_check_foreignness(fb_info))
return -ENOSYS;
- ret = do_remove_conflicting_framebuffers(fb_info->apertures,
- fb_info->fix.id,
- fb_is_primary_device(fb_info));
- if (ret)
- return ret;
+ do_remove_conflicting_framebuffers(fb_info->apertures,
+ fb_info->fix.id,
+ fb_is_primary_device(fb_info));
if (num_registered_fb == FB_MAX)
return -ENXIO;
@@ -1719,7 +1645,7 @@
fb_info->pixmap.access_align = 32;
fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
}
- }
+ }
fb_info->pixmap.offset = 0;
if (!fb_info->pixmap.blit_x)
@@ -1740,20 +1666,22 @@
fb_add_videomode(&mode, &fb_info->modelist);
registered_fb[i] = fb_info;
- event.info = fb_info;
+#ifdef CONFIG_GUMSTIX_AM200EPD
+ {
+ struct fb_event event;
+ event.info = fb_info;
+ fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
+ }
+#endif
+
if (!lockless_register_fb)
console_lock();
else
atomic_inc(&ignore_console_lock_warning);
- if (!lock_fb_info(fb_info)) {
- ret = -ENODEV;
- goto unlock_console;
- }
- ret = 0;
-
- fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
+ lock_fb_info(fb_info);
+ ret = fbcon_fb_registered(fb_info);
unlock_fb_info(fb_info);
-unlock_console:
+
if (!lockless_register_fb)
console_unlock();
else
@@ -1761,44 +1689,43 @@
return ret;
}
-static int unbind_console(struct fb_info *fb_info)
+static void unbind_console(struct fb_info *fb_info)
{
- struct fb_event event;
- int ret;
int i = fb_info->node;
- if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
- return -EINVAL;
+ if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info))
+ return;
console_lock();
- if (!lock_fb_info(fb_info)) {
- console_unlock();
- return -ENODEV;
- }
-
- event.info = fb_info;
- ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
+ lock_fb_info(fb_info);
+ fbcon_fb_unbind(fb_info);
unlock_fb_info(fb_info);
console_unlock();
-
- return ret;
}
-static int __unlink_framebuffer(struct fb_info *fb_info);
-
-static int do_unregister_framebuffer(struct fb_info *fb_info)
+static void unlink_framebuffer(struct fb_info *fb_info)
{
- struct fb_event event;
- int ret;
+ int i;
- ret = unbind_console(fb_info);
+ i = fb_info->node;
+ if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info))
+ return;
- if (ret)
- return -EINVAL;
+ if (!fb_info->dev)
+ return;
+
+ device_destroy(fb_class, MKDEV(FB_MAJOR, i));
pm_vt_switch_unregister(fb_info->dev);
- __unlink_framebuffer(fb_info);
+ unbind_console(fb_info);
+
+ fb_info->dev = NULL;
+}
+
+static void do_unregister_framebuffer(struct fb_info *fb_info)
+{
+ unlink_framebuffer(fb_info);
if (fb_info->pixmap.addr &&
(fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
kfree(fb_info->pixmap.addr);
@@ -1806,58 +1733,104 @@
registered_fb[fb_info->node] = NULL;
num_registered_fb--;
fb_cleanup_device(fb_info);
- event.info = fb_info;
+#ifdef CONFIG_GUMSTIX_AM200EPD
+ {
+ struct fb_event event;
+ event.info = fb_info;
+ fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
+ }
+#endif
console_lock();
- fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
+ fbcon_fb_unregistered(fb_info);
console_unlock();
/* this may free fb info */
put_fb_info(fb_info);
- return 0;
}
-static int __unlink_framebuffer(struct fb_info *fb_info)
-{
- int i;
-
- i = fb_info->node;
- if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
- return -EINVAL;
-
- if (fb_info->dev) {
- device_destroy(fb_class, MKDEV(FB_MAJOR, i));
- fb_info->dev = NULL;
- }
-
- return 0;
-}
-
-int unlink_framebuffer(struct fb_info *fb_info)
-{
- int ret;
-
- ret = __unlink_framebuffer(fb_info);
- if (ret)
- return ret;
-
- unbind_console(fb_info);
-
- return 0;
-}
-EXPORT_SYMBOL(unlink_framebuffer);
-
+/**
+ * remove_conflicting_framebuffers - remove firmware-configured framebuffers
+ * @a: memory range, users of which are to be removed
+ * @name: requesting driver name
+ * @primary: also kick vga16fb if present
+ *
+ * This function removes framebuffer devices (initialized by firmware/bootloader)
+ * which use memory range described by @a. If @a is NULL all such devices are
+ * removed.
+ */
int remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary)
{
- int ret;
+ bool do_free = false;
+
+ if (!a) {
+ a = alloc_apertures(1);
+ if (!a)
+ return -ENOMEM;
+
+ a->ranges[0].base = 0;
+ a->ranges[0].size = ~0;
+ do_free = true;
+ }
mutex_lock(®istration_lock);
- ret = do_remove_conflicting_framebuffers(a, name, primary);
+ do_remove_conflicting_framebuffers(a, name, primary);
mutex_unlock(®istration_lock);
- return ret;
+ if (do_free)
+ kfree(a);
+
+ return 0;
}
EXPORT_SYMBOL(remove_conflicting_framebuffers);
+
+/**
+ * remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
+ * @pdev: PCI device
+ * @name: requesting driver name
+ *
+ * This function removes framebuffer devices (eg. initialized by firmware)
+ * using memory range configured for any of @pdev's memory bars.
+ *
+ * The function assumes that PCI device with shadowed ROM drives a primary
+ * display and so kicks out vga16fb.
+ */
+int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name)
+{
+ struct apertures_struct *ap;
+ bool primary = false;
+ int err, idx, bar;
+
+ for (idx = 0, bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
+ if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
+ continue;
+ idx++;
+ }
+
+ ap = alloc_apertures(idx);
+ if (!ap)
+ return -ENOMEM;
+
+ for (idx = 0, bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
+ if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
+ continue;
+ ap->ranges[idx].base = pci_resource_start(pdev, bar);
+ ap->ranges[idx].size = pci_resource_len(pdev, bar);
+ pci_dbg(pdev, "%s: bar %d: 0x%lx -> 0x%lx\n", __func__, bar,
+ (unsigned long)pci_resource_start(pdev, bar),
+ (unsigned long)pci_resource_end(pdev, bar));
+ idx++;
+ }
+
+#ifdef CONFIG_X86
+ primary = pdev->resource[PCI_ROM_RESOURCE].flags &
+ IORESOURCE_ROM_SHADOW;
+#endif
+ err = remove_conflicting_framebuffers(ap, name, primary);
+ kfree(ap);
+ return err;
+}
+EXPORT_SYMBOL(remove_conflicting_pci_framebuffers);
/**
* register_framebuffer - registers a frame buffer device
@@ -1897,16 +1870,12 @@
* that the driver implements fb_open() and fb_release() to
* check that no processes are using the device.
*/
-int
+void
unregister_framebuffer(struct fb_info *fb_info)
{
- int ret;
-
mutex_lock(®istration_lock);
- ret = do_unregister_framebuffer(fb_info);
+ do_unregister_framebuffer(fb_info);
mutex_unlock(®istration_lock);
-
- return ret;
}
EXPORT_SYMBOL(unregister_framebuffer);
@@ -1921,15 +1890,14 @@
*/
void fb_set_suspend(struct fb_info *info, int state)
{
- struct fb_event event;
+ WARN_CONSOLE_UNLOCKED();
- event.info = info;
if (state) {
- fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
+ fbcon_suspended(info);
info->state = FBINFO_STATE_SUSPENDED;
} else {
info->state = FBINFO_STATE_RUNNING;
- fb_notifier_call_chain(FB_EVENT_RESUME, &event);
+ fbcon_resumed(info);
}
}
EXPORT_SYMBOL(fb_set_suspend);
@@ -1997,12 +1965,11 @@
int fb_new_modelist(struct fb_info *info)
{
- struct fb_event event;
struct fb_var_screeninfo var = info->var;
struct list_head *pos, *n;
struct fb_modelist *modelist;
struct fb_videomode *m, mode;
- int err = 1;
+ int err;
list_for_each_safe(pos, n, &info->modelist) {
modelist = list_entry(pos, struct fb_modelist, list);
@@ -2017,14 +1984,12 @@
}
}
- err = 1;
+ if (list_empty(&info->modelist))
+ return 1;
- if (!list_empty(&info->modelist)) {
- event.info = info;
- err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
- }
+ fbcon_new_modelist(info);
- return err;
+ return 0;
}
MODULE_LICENSE("GPL");
--
Gitblit v1.6.2