Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Generic System Framebuffers
0004  * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
0005  */
0006 
0007 /*
0008  * Simple-Framebuffer support
0009  * Create a platform-device for any available boot framebuffer. The
0010  * simple-framebuffer platform device is already available on DT systems, so
0011  * this module parses the global "screen_info" object and creates a suitable
0012  * platform device compatible with the "simple-framebuffer" DT object. If
0013  * the framebuffer is incompatible, we instead create a legacy
0014  * "vesa-framebuffer", "efi-framebuffer" or "platform-framebuffer" device and
0015  * pass the screen_info as platform_data. This allows legacy drivers
0016  * to pick these devices up without messing with simple-framebuffer drivers.
0017  * The global "screen_info" is still valid at all times.
0018  *
0019  * If CONFIG_SYSFB_SIMPLEFB is not selected, never register "simple-framebuffer"
0020  * platform devices, but only use legacy framebuffer devices for
0021  * backwards compatibility.
0022  *
0023  * TODO: We set the dev_id field of all platform-devices to 0. This allows
0024  * other OF/DT parsers to create such devices, too. However, they must
0025  * start at offset 1 for this to work.
0026  */
0027 
0028 #include <linux/err.h>
0029 #include <linux/init.h>
0030 #include <linux/kernel.h>
0031 #include <linux/mm.h>
0032 #include <linux/platform_data/simplefb.h>
0033 #include <linux/platform_device.h>
0034 #include <linux/screen_info.h>
0035 #include <linux/sysfb.h>
0036 
0037 static struct platform_device *pd;
0038 static DEFINE_MUTEX(disable_lock);
0039 static bool disabled;
0040 
0041 static bool sysfb_unregister(void)
0042 {
0043     if (IS_ERR_OR_NULL(pd))
0044         return false;
0045 
0046     platform_device_unregister(pd);
0047     pd = NULL;
0048 
0049     return true;
0050 }
0051 
0052 /**
0053  * sysfb_disable() - disable the Generic System Framebuffers support
0054  *
0055  * This disables the registration of system framebuffer devices that match the
0056  * generic drivers that make use of the system framebuffer set up by firmware.
0057  *
0058  * It also unregisters a device if this was already registered by sysfb_init().
0059  *
0060  * Context: The function can sleep. A @disable_lock mutex is acquired to serialize
0061  *          against sysfb_init(), that registers a system framebuffer device.
0062  */
0063 void sysfb_disable(void)
0064 {
0065     mutex_lock(&disable_lock);
0066     sysfb_unregister();
0067     disabled = true;
0068     mutex_unlock(&disable_lock);
0069 }
0070 EXPORT_SYMBOL_GPL(sysfb_disable);
0071 
0072 static __init int sysfb_init(void)
0073 {
0074     struct screen_info *si = &screen_info;
0075     struct simplefb_platform_data mode;
0076     const char *name;
0077     bool compatible;
0078     int ret = 0;
0079 
0080     mutex_lock(&disable_lock);
0081     if (disabled)
0082         goto unlock_mutex;
0083 
0084     /* try to create a simple-framebuffer device */
0085     compatible = sysfb_parse_mode(si, &mode);
0086     if (compatible) {
0087         pd = sysfb_create_simplefb(si, &mode);
0088         if (!IS_ERR(pd))
0089             goto unlock_mutex;
0090     }
0091 
0092     /* if the FB is incompatible, create a legacy framebuffer device */
0093     if (si->orig_video_isVGA == VIDEO_TYPE_EFI)
0094         name = "efi-framebuffer";
0095     else if (si->orig_video_isVGA == VIDEO_TYPE_VLFB)
0096         name = "vesa-framebuffer";
0097     else
0098         name = "platform-framebuffer";
0099 
0100     pd = platform_device_alloc(name, 0);
0101     if (!pd) {
0102         ret = -ENOMEM;
0103         goto unlock_mutex;
0104     }
0105 
0106     sysfb_apply_efi_quirks(pd);
0107 
0108     ret = platform_device_add_data(pd, si, sizeof(*si));
0109     if (ret)
0110         goto err;
0111 
0112     ret = platform_device_add(pd);
0113     if (ret)
0114         goto err;
0115 
0116     goto unlock_mutex;
0117 err:
0118     platform_device_put(pd);
0119 unlock_mutex:
0120     mutex_unlock(&disable_lock);
0121     return ret;
0122 }
0123 
0124 /* must execute after PCI subsystem for EFI quirks */
0125 device_initcall(sysfb_init);