blob: e8a0f2e56bccca77b6481873b23c286c3188e1cd [file] [log] [blame]
wdenkeeb1b772004-03-23 22:53:55 +00001/*
2 * (C) Copyright 2004
3 * Pierre Aubert, Staubli Faverges , <p.aubert@staubli.com>
Timur Tabia5dbdc82011-03-21 16:38:49 -05004 * Copyright 2011 Freescale Semiconductor, Inc.
wdenkeeb1b772004-03-23 22:53:55 +00005 *
Wolfgang Denk3765b3e2013-10-07 13:07:26 +02006 * SPDX-License-Identifier: GPL-2.0+
wdenkeeb1b772004-03-23 22:53:55 +00007 */
8
9/************************************************************************
10 Get Parameters for the video mode:
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020011 The default video mode can be defined in CONFIG_SYS_DEFAULT_VIDEO_MODE.
wdenkeeb1b772004-03-23 22:53:55 +000012 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>
Timur Tabia5dbdc82011-03-21 16:38:49 -050061#include <linux/ctype.h>
62
wdenkeeb1b772004-03-23 22:53:55 +000063#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] = {
Hans de Goede0c91d2572014-12-19 10:38:49 +010087 /* x y hz pixclk ps/kHz le ri up lo hs vs s vmode */
Hans de Goede92a88c32014-12-19 11:11:52 +010088#ifndef CONFIG_VIDEO_STD_TIMINGS
Hans de Goede0c91d2572014-12-19 10:38:49 +010089 { 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},
Hans de Goede92a88c32014-12-19 11:11:52 +010095#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
wdenkeeb1b772004-03-23 22:53:55 +0000103};
104
105/************************************************************************
106 * Get Parameters for the video mode:
107 */
108/*********************************************************************
109 * returns the length to the next seperator
110 */
111static int
112video_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
122static int
123video_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
152int video_get_params (struct ctfb_res_modes *pPar, char *penv)
153{
154 char *p, *s, *val_s;
Wolfgang Denk40ac78a2011-11-04 15:55:14 +0000155 int i = 0;
wdenkeeb1b772004-03-23 22:53:55 +0000156 int bpp;
157 int mode;
Wolfgang Denk40ac78a2011-11-04 15:55:14 +0000158
wdenkeeb1b772004-03-23 22:53:55 +0000159 /* first search for the environment containing the real param string */
160 s = penv;
Wolfgang Denk40ac78a2011-11-04 15:55:14 +0000161
162 if ((p = getenv (s)) != NULL)
wdenkeeb1b772004-03-23 22:53:55 +0000163 s = p;
Wolfgang Denk40ac78a2011-11-04 15:55:14 +0000164
165 /*
166 * in case of the bootargs line, we have to start
wdenkeeb1b772004-03-23 22:53:55 +0000167 * 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;
wdenkeeb1b772004-03-23 22:53:55 +0000176 mode = 0; /* default */
Wolfgang Denk40ac78a2011-11-04 15:55:14 +0000177
wdenkeeb1b772004-03-23 22:53:55 +0000178 while ((i = video_get_param_len (p, ',')) != 0) {
179 GET_OPTION ("mode:", mode)
180 p += i;
181 if (*p != 0)
182 p++; /* skip ',' */
183 }
Wolfgang Denk40ac78a2011-11-04 15:55:14 +0000184
wdenkeeb1b772004-03-23 22:53:55 +0000185 if (mode >= RES_MODES_COUNT)
186 mode = 0;
Wolfgang Denk40ac78a2011-11-04 15:55:14 +0000187
wdenkeeb1b772004-03-23 22:53:55 +0000188 *pPar = res_mode_init[mode]; /* copy default values */
189 bpp = 24 - ((mode % 3) * 8);
190 p = s; /* restart */
Wolfgang Denk40ac78a2011-11-04 15:55:14 +0000191
wdenkeeb1b772004-03-23 22:53:55 +0000192 while ((i = video_get_param_len (p, ',')) != 0) {
193 GET_OPTION ("x:", pPar->xres)
194 GET_OPTION ("y:", pPar->yres)
Hans de Goede0c91d2572014-12-19 10:38:49 +0100195 GET_OPTION ("refresh:", pPar->refresh)
wdenkeeb1b772004-03-23 22:53:55 +0000196 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)
Hans de Goede0c91d2572014-12-19 10:38:49 +0100205 GET_OPTION ("pclk_khz:", pPar->pixclock_khz)
wdenkeeb1b772004-03-23 22:53:55 +0000206 GET_OPTION ("depth:", bpp)
207 p += i;
208 if (*p != 0)
209 p++; /* skip ',' */
210 }
211 return bpp;
212}
Timur Tabia5dbdc82011-03-21 16:38:49 -0500213
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 */
228int 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}