162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Based on the fbdev code in drivers/video/fbdev/core/fb_cmdline: 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2014 Intel Corp 662306a36Sopenharmony_ci * Copyright (C) 1994 Martin Schaller 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * 2001 - Documented with DocBook 962306a36Sopenharmony_ci * - Brad Douglas <brad@neruo.com> 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 1262306a36Sopenharmony_ci * License. See the file COPYING in the main directory of this archive 1362306a36Sopenharmony_ci * for more details. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * Authors: 1662306a36Sopenharmony_ci * Daniel Vetter <daniel.vetter@ffwll.ch> 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <linux/fb.h> /* for FB_MAX */ 2062306a36Sopenharmony_ci#include <linux/init.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <video/cmdline.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* 2562306a36Sopenharmony_ci * FB_MAX is the maximum number of framebuffer devices and also 2662306a36Sopenharmony_ci * the maximum number of video= parameters. Although not directly 2762306a36Sopenharmony_ci * related to each other, it makes sense to keep it that way. 2862306a36Sopenharmony_ci */ 2962306a36Sopenharmony_cistatic const char *video_options[FB_MAX] __read_mostly; 3062306a36Sopenharmony_cistatic const char *video_option __read_mostly; 3162306a36Sopenharmony_cistatic int video_of_only __read_mostly; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic const char *__video_get_option_string(const char *name) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci const char *options = NULL; 3662306a36Sopenharmony_ci size_t name_len = 0; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci if (name) 3962306a36Sopenharmony_ci name_len = strlen(name); 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci if (name_len) { 4262306a36Sopenharmony_ci unsigned int i; 4362306a36Sopenharmony_ci const char *opt; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(video_options); ++i) { 4662306a36Sopenharmony_ci if (!video_options[i]) 4762306a36Sopenharmony_ci continue; 4862306a36Sopenharmony_ci if (video_options[i][0] == '\0') 4962306a36Sopenharmony_ci continue; 5062306a36Sopenharmony_ci opt = video_options[i]; 5162306a36Sopenharmony_ci if (!strncmp(opt, name, name_len) && opt[name_len] == ':') 5262306a36Sopenharmony_ci options = opt + name_len + 1; 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci /* No match, return global options */ 5762306a36Sopenharmony_ci if (!options) 5862306a36Sopenharmony_ci options = video_option; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci return options; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/** 6462306a36Sopenharmony_ci * video_get_options - get kernel boot parameters 6562306a36Sopenharmony_ci * @name: name of the output as it would appear in the boot parameter 6662306a36Sopenharmony_ci * line (video=<name>:<options>) 6762306a36Sopenharmony_ci * 6862306a36Sopenharmony_ci * Looks up the video= options for the given name. Names are connector 6962306a36Sopenharmony_ci * names with DRM, or driver names with fbdev. If no video option for 7062306a36Sopenharmony_ci * the name has been specified, the function returns the global video= 7162306a36Sopenharmony_ci * setting. A @name of NULL always returns the global video setting. 7262306a36Sopenharmony_ci * 7362306a36Sopenharmony_ci * Returns: 7462306a36Sopenharmony_ci * The string of video options for the given name, or NULL if no video 7562306a36Sopenharmony_ci * option has been specified. 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_ciconst char *video_get_options(const char *name) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci return __video_get_option_string(name); 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ciEXPORT_SYMBOL(video_get_options); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cibool __video_get_options(const char *name, const char **options, bool is_of) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci bool enabled = true; 8662306a36Sopenharmony_ci const char *opt = NULL; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci if (video_of_only && !is_of) 8962306a36Sopenharmony_ci enabled = false; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci opt = __video_get_option_string(name); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (options) 9462306a36Sopenharmony_ci *options = opt; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci return enabled; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ciEXPORT_SYMBOL(__video_get_options); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci/* 10162306a36Sopenharmony_ci * Process command line options for video adapters. This function is 10262306a36Sopenharmony_ci * a __setup and __init function. It only stores the options. Drivers 10362306a36Sopenharmony_ci * have to call video_get_options() as necessary. 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_cistatic int __init video_setup(char *options) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci if (!options || !*options) 10862306a36Sopenharmony_ci goto out; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci if (!strncmp(options, "ofonly", 6)) { 11162306a36Sopenharmony_ci video_of_only = true; 11262306a36Sopenharmony_ci goto out; 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci if (strchr(options, ':')) { 11662306a36Sopenharmony_ci /* named */ 11762306a36Sopenharmony_ci size_t i; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(video_options); i++) { 12062306a36Sopenharmony_ci if (!video_options[i]) { 12162306a36Sopenharmony_ci video_options[i] = options; 12262306a36Sopenharmony_ci break; 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci } else { 12662306a36Sopenharmony_ci /* global */ 12762306a36Sopenharmony_ci video_option = options; 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ciout: 13162306a36Sopenharmony_ci return 1; 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci__setup("video=", video_setup); 134