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 hz pixclk ps/kHz le ri up lo hs vs s vmode */ 88 #ifndef CONFIG_VIDEO_STD_TIMINGS 89 { 640, 480, 60, 39721, 25180, 40, 24, 32, 11, 96, 2, 0, FB_VMODE_NONINTERLACED}, 90 { 800, 600, 60, 27778, 36000, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED}, 91 {1024, 768, 60, 15384, 65000, 168, 8, 29, 3, 144, 4, 0, FB_VMODE_NONINTERLACED}, 92 { 960, 720, 80, 13100, 76335, 160, 40, 32, 8, 80, 4, 0, FB_VMODE_NONINTERLACED}, 93 {1152, 864, 60, 12004, 83300, 200, 64, 32, 16, 80, 4, 0, FB_VMODE_NONINTERLACED}, 94 {1280, 1024, 60, 9090, 110000, 200, 48, 26, 1, 184, 3, 0, FB_VMODE_NONINTERLACED}, 95 #else 96 { 640, 480, 60, 39683, 25200, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED}, 97 { 800, 600, 60, 25000, 40000, 88, 40, 23, 1, 128, 4, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED}, 98 {1024, 768, 60, 15384, 65000, 160, 24, 29, 3, 136, 6, 0, FB_VMODE_NONINTERLACED}, 99 { 960, 720, 75, 13468, 74250, 176, 72, 27, 1, 112, 2, 0, FB_VMODE_NONINTERLACED}, 100 {1152, 864, 75, 9259, 108000, 256, 64, 32, 1, 128, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED}, 101 {1280, 1024, 60, 9259, 108000, 248, 48, 38, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED}, 102 #endif 103 }; 104 105 /************************************************************************ 106 * Get Parameters for the video mode: 107 */ 108 /********************************************************************* 109 * returns the length to the next seperator 110 */ 111 static int 112 video_get_param_len (char *start, char sep) 113 { 114 int i = 0; 115 while ((*start != 0) && (*start != sep)) { 116 start++; 117 i++; 118 } 119 return i; 120 } 121 122 static int 123 video_search_param (char *start, char *param) 124 { 125 int len, totallen, i; 126 char *p = start; 127 len = strlen (param); 128 totallen = len + strlen (start); 129 for (i = 0; i < totallen; i++) { 130 if (strncmp (p++, param, len) == 0) 131 return (i); 132 } 133 return -1; 134 } 135 136 /*************************************************************** 137 * Get parameter via the environment as it is done for the 138 * linux kernel i.e: 139 * video=ctfb:x:800,xv:1280,y:600,yv:1024,depth:16,mode:0,pclk:25000, 140 * le:56,ri:48,up:26,lo:5,hs:152,vs:2,sync:0,vmode:0,accel:0 141 * 142 * penv is a pointer to the environment, containing the string, or the name of 143 * another environment variable. It could even be the term "bootargs" 144 */ 145 146 #define GET_OPTION(name,var) \ 147 if(strncmp(p,name,strlen(name))==0) { \ 148 val_s=p+strlen(name); \ 149 var=simple_strtoul(val_s, NULL, 10); \ 150 } 151 152 int video_get_params (struct ctfb_res_modes *pPar, char *penv) 153 { 154 char *p, *s, *val_s; 155 int i = 0; 156 int bpp; 157 int mode; 158 159 /* first search for the environment containing the real param string */ 160 s = penv; 161 162 if ((p = getenv (s)) != NULL) 163 s = p; 164 165 /* 166 * in case of the bootargs line, we have to start 167 * after "video=ctfb:" 168 */ 169 i = video_search_param (s, "video=ctfb:"); 170 if (i >= 0) { 171 s += i; 172 s += strlen ("video=ctfb:"); 173 } 174 /* search for mode as a default value */ 175 p = s; 176 mode = 0; /* default */ 177 178 while ((i = video_get_param_len (p, ',')) != 0) { 179 GET_OPTION ("mode:", mode) 180 p += i; 181 if (*p != 0) 182 p++; /* skip ',' */ 183 } 184 185 if (mode >= RES_MODES_COUNT) 186 mode = 0; 187 188 *pPar = res_mode_init[mode]; /* copy default values */ 189 bpp = 24 - ((mode % 3) * 8); 190 p = s; /* restart */ 191 192 while ((i = video_get_param_len (p, ',')) != 0) { 193 GET_OPTION ("x:", pPar->xres) 194 GET_OPTION ("y:", pPar->yres) 195 GET_OPTION ("refresh:", pPar->refresh) 196 GET_OPTION ("le:", pPar->left_margin) 197 GET_OPTION ("ri:", pPar->right_margin) 198 GET_OPTION ("up:", pPar->upper_margin) 199 GET_OPTION ("lo:", pPar->lower_margin) 200 GET_OPTION ("hs:", pPar->hsync_len) 201 GET_OPTION ("vs:", pPar->vsync_len) 202 GET_OPTION ("sync:", pPar->sync) 203 GET_OPTION ("vmode:", pPar->vmode) 204 GET_OPTION ("pclk:", pPar->pixclock) 205 GET_OPTION ("pclk_khz:", pPar->pixclock_khz) 206 GET_OPTION ("depth:", bpp) 207 p += i; 208 if (*p != 0) 209 p++; /* skip ',' */ 210 } 211 return bpp; 212 } 213 214 /* 215 * Parse the 'video-mode' environment variable 216 * 217 * Example: "video-mode=fslfb:1280x1024-32@60,monitor=dvi". See 218 * doc/README.video for more information on how to set the variable. 219 * 220 * @xres: returned value of X-resolution 221 * @yres: returned value of Y-resolution 222 * @depth: returned value of color depth 223 * @freq: returned value of monitor frequency 224 * @options: pointer to any remaining options, or NULL 225 * 226 * Returns 1 if valid values were found, 0 otherwise 227 */ 228 int video_get_video_mode(unsigned int *xres, unsigned int *yres, 229 unsigned int *depth, unsigned int *freq, const char **options) 230 { 231 char *p = getenv("video-mode"); 232 if (!p) 233 return 0; 234 235 /* Skip over the driver name, which we don't care about. */ 236 p = strchr(p, ':'); 237 if (!p) 238 return 0; 239 240 /* Get the X-resolution*/ 241 while (*p && !isdigit(*p)) 242 p++; 243 *xres = simple_strtoul(p, &p, 10); 244 if (!*xres) 245 return 0; 246 247 /* Get the Y-resolution */ 248 while (*p && !isdigit(*p)) 249 p++; 250 *yres = simple_strtoul(p, &p, 10); 251 if (!*yres) 252 return 0; 253 254 /* Get the depth */ 255 while (*p && !isdigit(*p)) 256 p++; 257 *depth = simple_strtoul(p, &p, 10); 258 if (!*depth) 259 return 0; 260 261 /* Get the frequency */ 262 while (*p && !isdigit(*p)) 263 p++; 264 *freq = simple_strtoul(p, &p, 10); 265 if (!*freq) 266 return 0; 267 268 /* Find the extra options, if any */ 269 p = strchr(p, ','); 270 *options = p ? p + 1 : NULL; 271 272 return 1; 273 } 274