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