1 /* 2 * (C) Copyright 2004 3 * Pierre Aubert, Staubli Faverges , <p.aubert@staubli.com> 4 * Copyright 2011 Freescale Semiconductor, Inc. 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 /************************************************************************ 10 Get Parameters for the video mode: 11 The default video mode can be defined in CONFIG_SYS_DEFAULT_VIDEO_MODE. 12 If undefined, default video mode is set to 0x301 13 Parameters can be set via the variable "videomode" in the environment. 14 2 diferent ways are possible: 15 "videomode=301" - 301 is a hexadecimal number describing the VESA 16 mode. Following modes are implemented: 17 18 Colors 640x480 800x600 1024x768 1152x864 1280x1024 19 --------+--------------------------------------------- 20 8 bits | 0x301 0x303 0x305 0x161 0x307 21 15 bits | 0x310 0x313 0x316 0x162 0x319 22 16 bits | 0x311 0x314 0x317 0x163 0x31A 23 24 bits | 0x312 0x315 0x318 ? 0x31B 24 --------+--------------------------------------------- 25 "videomode=bootargs" 26 - the parameters are parsed from the bootargs. 27 The format is "NAME:VALUE,NAME:VALUE" etc. 28 Ex.: 29 "bootargs=video=ctfb:x:800,y:600,depth:16,pclk:25000" 30 Parameters not included in the list will be taken from 31 the default mode, which is one of the following: 32 mode:0 640x480x24 33 mode:1 800x600x16 34 mode:2 1024x768x8 35 mode:3 960x720x24 36 mode:4 1152x864x16 37 mode:5 1280x1024x8 38 39 if "mode" is not provided within the parameter list, 40 mode:0 is assumed. 41 Following parameters are supported: 42 x xres = visible resolution horizontal 43 y yres = visible resolution vertical 44 pclk pixelclocks in pico sec 45 le left_marging time from sync to picture in pixelclocks 46 ri right_marging time from picture to sync in pixelclocks 47 up upper_margin time from sync to picture 48 lo lower_margin 49 hs hsync_len length of horizontal sync 50 vs vsync_len length of vertical sync 51 sync see FB_SYNC_* 52 vmode see FB_VMODE_* 53 depth Color depth in bits per pixel 54 All other parameters in the variable bootargs are ignored. 55 It is also possible to set the parameters direct in the 56 variable "videomode", or in another variable i.e. 57 "myvideo" and setting the variable "videomode=myvideo".. 58 ****************************************************************************/ 59 60 #include <common.h> 61 #include <linux/ctype.h> 62 63 #include "videomodes.h" 64 65 const struct ctfb_vesa_modes vesa_modes[VESA_MODES_COUNT] = { 66 {0x301, RES_MODE_640x480, 8}, 67 {0x310, RES_MODE_640x480, 15}, 68 {0x311, RES_MODE_640x480, 16}, 69 {0x312, RES_MODE_640x480, 24}, 70 {0x303, RES_MODE_800x600, 8}, 71 {0x313, RES_MODE_800x600, 15}, 72 {0x314, RES_MODE_800x600, 16}, 73 {0x315, RES_MODE_800x600, 24}, 74 {0x305, RES_MODE_1024x768, 8}, 75 {0x316, RES_MODE_1024x768, 15}, 76 {0x317, RES_MODE_1024x768, 16}, 77 {0x318, RES_MODE_1024x768, 24}, 78 {0x161, RES_MODE_1152x864, 8}, 79 {0x162, RES_MODE_1152x864, 15}, 80 {0x163, RES_MODE_1152x864, 16}, 81 {0x307, RES_MODE_1280x1024, 8}, 82 {0x319, RES_MODE_1280x1024, 15}, 83 {0x31A, RES_MODE_1280x1024, 16}, 84 {0x31B, RES_MODE_1280x1024, 24}, 85 }; 86 const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = { 87 /* x y pixclk le ri up lo hs vs s vmode */ 88 {640, 480, 39721, 40, 24, 32, 11, 96, 2, 0, FB_VMODE_NONINTERLACED}, 89 {800, 600, 27778, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED}, 90 {1024, 768, 15384, 168, 8, 29, 3, 144, 4, 0, FB_VMODE_NONINTERLACED}, 91 {960, 720, 13100, 160, 40, 32, 8, 80, 4, 0, FB_VMODE_NONINTERLACED}, 92 {1152, 864, 12004, 200, 64, 32, 16, 80, 4, 0, FB_VMODE_NONINTERLACED}, 93 {1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0, FB_VMODE_NONINTERLACED}, 94 }; 95 96 /************************************************************************ 97 * Get Parameters for the video mode: 98 */ 99 /********************************************************************* 100 * returns the length to the next seperator 101 */ 102 static int 103 video_get_param_len (char *start, char sep) 104 { 105 int i = 0; 106 while ((*start != 0) && (*start != sep)) { 107 start++; 108 i++; 109 } 110 return i; 111 } 112 113 static int 114 video_search_param (char *start, char *param) 115 { 116 int len, totallen, i; 117 char *p = start; 118 len = strlen (param); 119 totallen = len + strlen (start); 120 for (i = 0; i < totallen; i++) { 121 if (strncmp (p++, param, len) == 0) 122 return (i); 123 } 124 return -1; 125 } 126 127 /*************************************************************** 128 * Get parameter via the environment as it is done for the 129 * linux kernel i.e: 130 * video=ctfb:x:800,xv:1280,y:600,yv:1024,depth:16,mode:0,pclk:25000, 131 * le:56,ri:48,up:26,lo:5,hs:152,vs:2,sync:0,vmode:0,accel:0 132 * 133 * penv is a pointer to the environment, containing the string, or the name of 134 * another environment variable. It could even be the term "bootargs" 135 */ 136 137 #define GET_OPTION(name,var) \ 138 if(strncmp(p,name,strlen(name))==0) { \ 139 val_s=p+strlen(name); \ 140 var=simple_strtoul(val_s, NULL, 10); \ 141 } 142 143 int video_get_params (struct ctfb_res_modes *pPar, char *penv) 144 { 145 char *p, *s, *val_s; 146 int i = 0; 147 int bpp; 148 int mode; 149 150 /* first search for the environment containing the real param string */ 151 s = penv; 152 153 if ((p = getenv (s)) != NULL) 154 s = p; 155 156 /* 157 * in case of the bootargs line, we have to start 158 * after "video=ctfb:" 159 */ 160 i = video_search_param (s, "video=ctfb:"); 161 if (i >= 0) { 162 s += i; 163 s += strlen ("video=ctfb:"); 164 } 165 /* search for mode as a default value */ 166 p = s; 167 mode = 0; /* default */ 168 169 while ((i = video_get_param_len (p, ',')) != 0) { 170 GET_OPTION ("mode:", mode) 171 p += i; 172 if (*p != 0) 173 p++; /* skip ',' */ 174 } 175 176 if (mode >= RES_MODES_COUNT) 177 mode = 0; 178 179 *pPar = res_mode_init[mode]; /* copy default values */ 180 bpp = 24 - ((mode % 3) * 8); 181 p = s; /* restart */ 182 183 while ((i = video_get_param_len (p, ',')) != 0) { 184 GET_OPTION ("x:", pPar->xres) 185 GET_OPTION ("y:", pPar->yres) 186 GET_OPTION ("le:", pPar->left_margin) 187 GET_OPTION ("ri:", pPar->right_margin) 188 GET_OPTION ("up:", pPar->upper_margin) 189 GET_OPTION ("lo:", pPar->lower_margin) 190 GET_OPTION ("hs:", pPar->hsync_len) 191 GET_OPTION ("vs:", pPar->vsync_len) 192 GET_OPTION ("sync:", pPar->sync) 193 GET_OPTION ("vmode:", pPar->vmode) 194 GET_OPTION ("pclk:", pPar->pixclock) 195 GET_OPTION ("depth:", bpp) 196 p += i; 197 if (*p != 0) 198 p++; /* skip ',' */ 199 } 200 return bpp; 201 } 202 203 /* 204 * Parse the 'video-mode' environment variable 205 * 206 * Example: "video-mode=fslfb:1280x1024-32@60,monitor=dvi". See 207 * doc/README.video for more information on how to set the variable. 208 * 209 * @xres: returned value of X-resolution 210 * @yres: returned value of Y-resolution 211 * @depth: returned value of color depth 212 * @freq: returned value of monitor frequency 213 * @options: pointer to any remaining options, or NULL 214 * 215 * Returns 1 if valid values were found, 0 otherwise 216 */ 217 int video_get_video_mode(unsigned int *xres, unsigned int *yres, 218 unsigned int *depth, unsigned int *freq, const char **options) 219 { 220 char *p = getenv("video-mode"); 221 if (!p) 222 return 0; 223 224 /* Skip over the driver name, which we don't care about. */ 225 p = strchr(p, ':'); 226 if (!p) 227 return 0; 228 229 /* Get the X-resolution*/ 230 while (*p && !isdigit(*p)) 231 p++; 232 *xres = simple_strtoul(p, &p, 10); 233 if (!*xres) 234 return 0; 235 236 /* Get the Y-resolution */ 237 while (*p && !isdigit(*p)) 238 p++; 239 *yres = simple_strtoul(p, &p, 10); 240 if (!*yres) 241 return 0; 242 243 /* Get the depth */ 244 while (*p && !isdigit(*p)) 245 p++; 246 *depth = simple_strtoul(p, &p, 10); 247 if (!*depth) 248 return 0; 249 250 /* Get the frequency */ 251 while (*p && !isdigit(*p)) 252 p++; 253 *freq = simple_strtoul(p, &p, 10); 254 if (!*freq) 255 return 0; 256 257 /* Find the extra options, if any */ 258 p = strchr(p, ','); 259 *options = p ? p + 1 : NULL; 260 261 return 1; 262 } 263