]>
Commit | Line | Data |
---|---|---|
eeb1b77b WD |
1 | /* |
2 | * (C) Copyright 2004 | |
3 | * Pierre Aubert, Staubli Faverges , <p.aubert@staubli.com> | |
a5dbdc81 | 4 | * Copyright 2011 Freescale Semiconductor, Inc. |
eeb1b77b | 5 | * |
1a459660 | 6 | * SPDX-License-Identifier: GPL-2.0+ |
eeb1b77b WD |
7 | */ |
8 | ||
9 | /************************************************************************ | |
10 | Get Parameters for the video mode: | |
6d0f6bcf | 11 | The default video mode can be defined in CONFIG_SYS_DEFAULT_VIDEO_MODE. |
eeb1b77b WD |
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> | |
a5dbdc81 TT |
61 | #include <linux/ctype.h> |
62 | ||
eeb1b77b WD |
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; | |
40ac78a9 | 146 | int i = 0; |
eeb1b77b WD |
147 | int bpp; |
148 | int mode; | |
40ac78a9 | 149 | |
eeb1b77b WD |
150 | /* first search for the environment containing the real param string */ |
151 | s = penv; | |
40ac78a9 WD |
152 | |
153 | if ((p = getenv (s)) != NULL) | |
eeb1b77b | 154 | s = p; |
40ac78a9 WD |
155 | |
156 | /* | |
157 | * in case of the bootargs line, we have to start | |
eeb1b77b WD |
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; | |
eeb1b77b | 167 | mode = 0; /* default */ |
40ac78a9 | 168 | |
eeb1b77b WD |
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 | } | |
40ac78a9 | 175 | |
eeb1b77b WD |
176 | if (mode >= RES_MODES_COUNT) |
177 | mode = 0; | |
40ac78a9 | 178 | |
eeb1b77b WD |
179 | *pPar = res_mode_init[mode]; /* copy default values */ |
180 | bpp = 24 - ((mode % 3) * 8); | |
181 | p = s; /* restart */ | |
40ac78a9 | 182 | |
eeb1b77b WD |
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 | } | |
a5dbdc81 TT |
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 | } |