]> git.ipfire.org Git - thirdparty/u-boot.git/blame - drivers/video/videomodes.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[thirdparty/u-boot.git] / drivers / video / videomodes.c
CommitLineData
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
65const 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};
86const 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 */
102static int
103video_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
113static int
114video_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
143int 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 */
217int 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}