1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60#include <common.h>
61#include <edid.h>
62#include <errno.h>
63#include <linux/ctype.h>
64
65#include "videomodes.h"
66
67const struct ctfb_vesa_modes vesa_modes[VESA_MODES_COUNT] = {
68 {0x301, RES_MODE_640x480, 8},
69 {0x310, RES_MODE_640x480, 15},
70 {0x311, RES_MODE_640x480, 16},
71 {0x312, RES_MODE_640x480, 24},
72 {0x303, RES_MODE_800x600, 8},
73 {0x313, RES_MODE_800x600, 15},
74 {0x314, RES_MODE_800x600, 16},
75 {0x315, RES_MODE_800x600, 24},
76 {0x305, RES_MODE_1024x768, 8},
77 {0x316, RES_MODE_1024x768, 15},
78 {0x317, RES_MODE_1024x768, 16},
79 {0x318, RES_MODE_1024x768, 24},
80 {0x161, RES_MODE_1152x864, 8},
81 {0x162, RES_MODE_1152x864, 15},
82 {0x163, RES_MODE_1152x864, 16},
83 {0x307, RES_MODE_1280x1024, 8},
84 {0x319, RES_MODE_1280x1024, 15},
85 {0x31A, RES_MODE_1280x1024, 16},
86 {0x31B, RES_MODE_1280x1024, 24},
87};
88const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {
89
90#ifndef CONFIG_VIDEO_STD_TIMINGS
91 { 640, 480, 60, 39721, 25180, 40, 24, 32, 11, 96, 2, 0, FB_VMODE_NONINTERLACED},
92 { 800, 600, 60, 27778, 36000, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED},
93 {1024, 768, 60, 15384, 65000, 168, 8, 29, 3, 144, 4, 0, FB_VMODE_NONINTERLACED},
94 { 960, 720, 80, 13100, 76335, 160, 40, 32, 8, 80, 4, 0, FB_VMODE_NONINTERLACED},
95 {1152, 864, 60, 12004, 83300, 200, 64, 32, 16, 80, 4, 0, FB_VMODE_NONINTERLACED},
96 {1280, 1024, 60, 9090, 110000, 200, 48, 26, 1, 184, 3, 0, FB_VMODE_NONINTERLACED},
97#else
98 { 640, 480, 60, 39683, 25200, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED},
99 { 800, 600, 60, 25000, 40000, 88, 40, 23, 1, 128, 4, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
100 {1024, 768, 60, 15384, 65000, 160, 24, 29, 3, 136, 6, 0, FB_VMODE_NONINTERLACED},
101 { 960, 720, 75, 13468, 74250, 176, 72, 27, 1, 112, 2, 0, FB_VMODE_NONINTERLACED},
102 {1152, 864, 75, 9259, 108000, 256, 64, 32, 1, 128, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
103 {1280, 1024, 60, 9259, 108000, 248, 48, 38, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
104#endif
105 {1280, 720, 60, 13468, 74250, 220, 110, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
106 {1360, 768, 60, 11696, 85500, 256, 64, 17, 3, 112, 7, 0, FB_VMODE_NONINTERLACED},
107 {1920, 1080, 60, 6734, 148500, 148, 88, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
108 {1920, 1200, 60, 6494, 154000, 80, 48, 26, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED},
109};
110
111
112
113
114
115
116
117static int
118video_get_param_len(const char *start, char sep)
119{
120 int i = 0;
121 while ((*start != 0) && (*start != sep)) {
122 start++;
123 i++;
124 }
125 return i;
126}
127
128static int
129video_search_param (char *start, char *param)
130{
131 int len, totallen, i;
132 char *p = start;
133 len = strlen (param);
134 totallen = len + strlen (start);
135 for (i = 0; i < totallen; i++) {
136 if (strncmp (p++, param, len) == 0)
137 return (i);
138 }
139 return -1;
140}
141
142
143
144
145
146
147
148
149
150
151
152#define GET_OPTION(name,var) \
153 if(strncmp(p,name,strlen(name))==0) { \
154 val_s=p+strlen(name); \
155 var=simple_strtoul(val_s, NULL, 10); \
156 }
157
158int video_get_params (struct ctfb_res_modes *pPar, char *penv)
159{
160 char *p, *s, *val_s;
161 int i = 0;
162 int bpp;
163 int mode;
164
165
166 s = penv;
167
168 if ((p = getenv (s)) != NULL)
169 s = p;
170
171
172
173
174
175 i = video_search_param (s, "video=ctfb:");
176 if (i >= 0) {
177 s += i;
178 s += strlen ("video=ctfb:");
179 }
180
181 p = s;
182 mode = 0;
183
184 while ((i = video_get_param_len (p, ',')) != 0) {
185 GET_OPTION ("mode:", mode)
186 p += i;
187 if (*p != 0)
188 p++;
189 }
190
191 if (mode >= RES_MODES_COUNT)
192 mode = 0;
193
194 *pPar = res_mode_init[mode];
195 bpp = 24 - ((mode % 3) * 8);
196 p = s;
197
198 while ((i = video_get_param_len (p, ',')) != 0) {
199 GET_OPTION ("x:", pPar->xres)
200 GET_OPTION ("y:", pPar->yres)
201 GET_OPTION ("refresh:", pPar->refresh)
202 GET_OPTION ("le:", pPar->left_margin)
203 GET_OPTION ("ri:", pPar->right_margin)
204 GET_OPTION ("up:", pPar->upper_margin)
205 GET_OPTION ("lo:", pPar->lower_margin)
206 GET_OPTION ("hs:", pPar->hsync_len)
207 GET_OPTION ("vs:", pPar->vsync_len)
208 GET_OPTION ("sync:", pPar->sync)
209 GET_OPTION ("vmode:", pPar->vmode)
210 GET_OPTION ("pclk:", pPar->pixclock)
211 GET_OPTION ("pclk_khz:", pPar->pixclock_khz)
212 GET_OPTION ("depth:", bpp)
213 p += i;
214 if (*p != 0)
215 p++;
216 }
217 return bpp;
218}
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234int video_get_video_mode(unsigned int *xres, unsigned int *yres,
235 unsigned int *depth, unsigned int *freq, const char **options)
236{
237 char *p = getenv("video-mode");
238 if (!p)
239 return 0;
240
241
242 p = strchr(p, ':');
243 if (!p)
244 return 0;
245
246
247 while (*p && !isdigit(*p))
248 p++;
249 *xres = simple_strtoul(p, &p, 10);
250 if (!*xres)
251 return 0;
252
253
254 while (*p && !isdigit(*p))
255 p++;
256 *yres = simple_strtoul(p, &p, 10);
257 if (!*yres)
258 return 0;
259
260
261 while (*p && !isdigit(*p))
262 p++;
263 *depth = simple_strtoul(p, &p, 10);
264 if (!*depth)
265 return 0;
266
267
268 while (*p && !isdigit(*p))
269 p++;
270 *freq = simple_strtoul(p, &p, 10);
271 if (!*freq)
272 return 0;
273
274
275 p = strchr(p, ',');
276 *options = p ? p + 1 : NULL;
277
278 return 1;
279}
280
281
282
283
284
285
286
287
288
289
290
291
292void video_get_ctfb_res_modes(int default_mode, unsigned int default_depth,
293 const struct ctfb_res_modes **mode_ret,
294 unsigned int *depth_ret,
295 const char **options)
296{
297 unsigned int i, xres, yres, depth, refresh;
298
299 *mode_ret = &res_mode_init[default_mode];
300 *depth_ret = default_depth;
301 *options = NULL;
302
303 if (!video_get_video_mode(&xres, &yres, &depth, &refresh, options))
304 return;
305
306 for (i = 0; i < RES_MODES_COUNT; i++) {
307 if (res_mode_init[i].xres == xres &&
308 res_mode_init[i].yres == yres &&
309 res_mode_init[i].refresh == refresh) {
310 *mode_ret = &res_mode_init[i];
311 *depth_ret = depth;
312 return;
313 }
314 }
315
316 printf("video-mode %dx%d-%d@%d not available, falling back to %dx%d-%d@%d\n",
317 xres, yres, depth, refresh, (*mode_ret)->xres,
318 (*mode_ret)->yres, *depth_ret, (*mode_ret)->refresh);
319}
320
321
322
323
324
325
326
327
328
329
330
331void video_get_option_string(const char *options, const char *name,
332 char *dest, int dest_len, const char *def)
333{
334 const char *p = options;
335 const int name_len = strlen(name);
336 int i, len;
337
338 while (p && (i = video_get_param_len(p, ',')) != 0) {
339 if (strncmp(p, name, name_len) == 0 && p[name_len] == '=') {
340 len = i - (name_len + 1);
341 if (len >= dest_len)
342 len = dest_len - 1;
343 memcpy(dest, &p[name_len + 1], len);
344 dest[len] = 0;
345 return;
346 }
347 p += i;
348 if (*p != 0)
349 p++;
350 }
351 strcpy(dest, def);
352}
353
354
355
356
357
358
359
360
361
362int video_get_option_int(const char *options, const char *name, int def)
363{
364 const char *p = options;
365 const int name_len = strlen(name);
366 int i;
367
368 while (p && (i = video_get_param_len(p, ',')) != 0) {
369 if (strncmp(p, name, name_len) == 0 && p[name_len] == '=')
370 return simple_strtoul(&p[name_len + 1], NULL, 10);
371
372 p += i;
373 if (*p != 0)
374 p++;
375 }
376 return def;
377}
378
379
380
381
382
383
384
385
386
387int video_edid_dtd_to_ctfb_res_modes(struct edid_detailed_timing *t,
388 struct ctfb_res_modes *mode)
389{
390 int margin, h_total, v_total;
391
392
393 if (EDID_DETAILED_TIMING_PIXEL_CLOCK(*t) == 0 ||
394 EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(*t) == 0 ||
395 EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*t) == 0 ||
396 EDID_DETAILED_TIMING_VERTICAL_ACTIVE(*t) == 0 ||
397 EDID_DETAILED_TIMING_VERTICAL_BLANKING(*t) == 0 ||
398 EDID_DETAILED_TIMING_HSYNC_OFFSET(*t) == 0 ||
399 EDID_DETAILED_TIMING_HSYNC_PULSE_WIDTH(*t) == 0 ||
400 EDID_DETAILED_TIMING_VSYNC_OFFSET(*t) == 0 ||
401 EDID_DETAILED_TIMING_VSYNC_PULSE_WIDTH(*t) == 0 ||
402
403 EDID_DETAILED_TIMING_FLAG_STEREO(*t) != 0)
404 return -EINVAL;
405
406 mode->xres = EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(*t);
407 mode->yres = EDID_DETAILED_TIMING_VERTICAL_ACTIVE(*t);
408
409 h_total = mode->xres + EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*t);
410 v_total = mode->yres + EDID_DETAILED_TIMING_VERTICAL_BLANKING(*t);
411 mode->refresh = EDID_DETAILED_TIMING_PIXEL_CLOCK(*t) /
412 (h_total * v_total);
413
414 mode->pixclock_khz = EDID_DETAILED_TIMING_PIXEL_CLOCK(*t) / 1000;
415 mode->pixclock = 1000000000L / mode->pixclock_khz;
416
417 mode->right_margin = EDID_DETAILED_TIMING_HSYNC_OFFSET(*t);
418 mode->hsync_len = EDID_DETAILED_TIMING_HSYNC_PULSE_WIDTH(*t);
419 margin = EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*t) -
420 (mode->right_margin + mode->hsync_len);
421 if (margin <= 0)
422 return -EINVAL;
423
424 mode->left_margin = margin;
425
426 mode->lower_margin = EDID_DETAILED_TIMING_VSYNC_OFFSET(*t);
427 mode->vsync_len = EDID_DETAILED_TIMING_VSYNC_PULSE_WIDTH(*t);
428 margin = EDID_DETAILED_TIMING_VERTICAL_BLANKING(*t) -
429 (mode->lower_margin + mode->vsync_len);
430 if (margin <= 0)
431 return -EINVAL;
432
433 mode->upper_margin = margin;
434
435 mode->sync = 0;
436 if (EDID_DETAILED_TIMING_FLAG_HSYNC_POLARITY(*t))
437 mode->sync |= FB_SYNC_HOR_HIGH_ACT;
438 if (EDID_DETAILED_TIMING_FLAG_VSYNC_POLARITY(*t))
439 mode->sync |= FB_SYNC_VERT_HIGH_ACT;
440
441 if (EDID_DETAILED_TIMING_FLAG_INTERLACED(*t))
442 mode->vmode = FB_VMODE_INTERLACED;
443 else
444 mode->vmode = FB_VMODE_NONINTERLACED;
445
446 return 0;
447}
448