1d391c582SJavier Martinez Canillas // SPDX-License-Identifier: GPL-2.0-or-later 2d391c582SJavier Martinez Canillas /* 38633ef82SJavier Martinez Canillas * Generic System Framebuffers 4d391c582SJavier Martinez Canillas * Copyright (c) 2012-2013 David Herrmann <[email protected]> 5d391c582SJavier Martinez Canillas */ 6d391c582SJavier Martinez Canillas 7d391c582SJavier Martinez Canillas /* 88633ef82SJavier Martinez Canillas * Simple-Framebuffer support 9d391c582SJavier Martinez Canillas * Create a platform-device for any available boot framebuffer. The 10d391c582SJavier Martinez Canillas * simple-framebuffer platform device is already available on DT systems, so 11d391c582SJavier Martinez Canillas * this module parses the global "screen_info" object and creates a suitable 12d391c582SJavier Martinez Canillas * platform device compatible with the "simple-framebuffer" DT object. If 13d391c582SJavier Martinez Canillas * the framebuffer is incompatible, we instead create a legacy 14d391c582SJavier Martinez Canillas * "vesa-framebuffer", "efi-framebuffer" or "platform-framebuffer" device and 15d391c582SJavier Martinez Canillas * pass the screen_info as platform_data. This allows legacy drivers 16d391c582SJavier Martinez Canillas * to pick these devices up without messing with simple-framebuffer drivers. 17d391c582SJavier Martinez Canillas * The global "screen_info" is still valid at all times. 18d391c582SJavier Martinez Canillas * 198633ef82SJavier Martinez Canillas * If CONFIG_SYSFB_SIMPLEFB is not selected, never register "simple-framebuffer" 20d391c582SJavier Martinez Canillas * platform devices, but only use legacy framebuffer devices for 21d391c582SJavier Martinez Canillas * backwards compatibility. 22d391c582SJavier Martinez Canillas * 23d391c582SJavier Martinez Canillas * TODO: We set the dev_id field of all platform-devices to 0. This allows 248633ef82SJavier Martinez Canillas * other OF/DT parsers to create such devices, too. However, they must 25d391c582SJavier Martinez Canillas * start at offset 1 for this to work. 26d391c582SJavier Martinez Canillas */ 27d391c582SJavier Martinez Canillas 28d391c582SJavier Martinez Canillas #include <linux/err.h> 29d391c582SJavier Martinez Canillas #include <linux/init.h> 30d391c582SJavier Martinez Canillas #include <linux/kernel.h> 31d391c582SJavier Martinez Canillas #include <linux/mm.h> 32d391c582SJavier Martinez Canillas #include <linux/platform_data/simplefb.h> 33d391c582SJavier Martinez Canillas #include <linux/platform_device.h> 34d391c582SJavier Martinez Canillas #include <linux/screen_info.h> 35d391c582SJavier Martinez Canillas #include <linux/sysfb.h> 36d391c582SJavier Martinez Canillas 37d391c582SJavier Martinez Canillas static __init int sysfb_init(void) 38d391c582SJavier Martinez Canillas { 39d391c582SJavier Martinez Canillas struct screen_info *si = &screen_info; 40d391c582SJavier Martinez Canillas struct simplefb_platform_data mode; 41d391c582SJavier Martinez Canillas struct platform_device *pd; 42d391c582SJavier Martinez Canillas const char *name; 43d391c582SJavier Martinez Canillas bool compatible; 44d391c582SJavier Martinez Canillas int ret; 45d391c582SJavier Martinez Canillas 46d391c582SJavier Martinez Canillas /* try to create a simple-framebuffer device */ 478633ef82SJavier Martinez Canillas compatible = sysfb_parse_mode(si, &mode); 48d391c582SJavier Martinez Canillas if (compatible) { 49*0949ee75SJavier Martinez Canillas pd = sysfb_create_simplefb(si, &mode); 50*0949ee75SJavier Martinez Canillas if (!IS_ERR(pd)) 51d391c582SJavier Martinez Canillas return 0; 52d391c582SJavier Martinez Canillas } 53d391c582SJavier Martinez Canillas 54d391c582SJavier Martinez Canillas /* if the FB is incompatible, create a legacy framebuffer device */ 55d391c582SJavier Martinez Canillas if (si->orig_video_isVGA == VIDEO_TYPE_EFI) 56d391c582SJavier Martinez Canillas name = "efi-framebuffer"; 57d391c582SJavier Martinez Canillas else if (si->orig_video_isVGA == VIDEO_TYPE_VLFB) 58d391c582SJavier Martinez Canillas name = "vesa-framebuffer"; 59d391c582SJavier Martinez Canillas else 60d391c582SJavier Martinez Canillas name = "platform-framebuffer"; 61d391c582SJavier Martinez Canillas 628633ef82SJavier Martinez Canillas pd = platform_device_alloc(name, 0); 638633ef82SJavier Martinez Canillas if (!pd) 648633ef82SJavier Martinez Canillas return -ENOMEM; 658633ef82SJavier Martinez Canillas 668633ef82SJavier Martinez Canillas sysfb_apply_efi_quirks(pd); 678633ef82SJavier Martinez Canillas 688633ef82SJavier Martinez Canillas ret = platform_device_add_data(pd, si, sizeof(*si)); 698633ef82SJavier Martinez Canillas if (ret) 708633ef82SJavier Martinez Canillas goto err; 718633ef82SJavier Martinez Canillas 728633ef82SJavier Martinez Canillas ret = platform_device_add(pd); 738633ef82SJavier Martinez Canillas if (ret) 748633ef82SJavier Martinez Canillas goto err; 758633ef82SJavier Martinez Canillas 768633ef82SJavier Martinez Canillas return 0; 778633ef82SJavier Martinez Canillas err: 788633ef82SJavier Martinez Canillas platform_device_put(pd); 798633ef82SJavier Martinez Canillas return ret; 80d391c582SJavier Martinez Canillas } 81d391c582SJavier Martinez Canillas 82d391c582SJavier Martinez Canillas /* must execute after PCI subsystem for EFI quirks */ 83d391c582SJavier Martinez Canillas device_initcall(sysfb_init); 84