*/
#include <linux/module.h>
-#include <linux/tty.h>
#include <linux/fb.h>
-#include <linux/sched.h>
#undef DEBUG
* Standard video mode definitions (taken from XFree86)
*/
-#define DEFAULT_MODEDB_INDEX 0
-
static const struct fb_videomode modedb[] = {
{
/* 640x400 @ 70 Hz, 31.5 kHz hsync */
NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
}, {
+ /* 1680x1050 @ 60 Hz, 65.191 kHz hsync */
+ NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ }, {
/* 1600x1200 @ 85 Hz, 105.77 kHz hsync */
NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3,
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
FB_VMODE_NONINTERLACED
+ }, {
+ /* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */
+ NULL, 60, 1152, 768, 15386, 158, 26, 29, 3, 136, 6,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ }, {
+ /* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */
+ NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5,
+ 0, FB_VMODE_NONINTERLACED
},
};
for (;; name++) {
switch (*name) {
- case '0'...'9':
+ case '0' ... '9':
val = 10*val+(*name-'0');
break;
default:
/* Set up defaults */
if (!db) {
db = modedb;
- dbsize = sizeof(modedb)/sizeof(*modedb);
+ dbsize = ARRAY_SIZE(modedb);
}
+
if (!default_mode)
- default_mode = &modedb[DEFAULT_MODEDB_INDEX];
+ default_mode = &db[0];
+
if (!default_bpp)
default_bpp = 8;
} else
goto done;
break;
- case '0'...'9':
+ case '0' ... '9':
break;
case 'M':
if (!yres_specified)
diff = refresh;
best = -1;
for (i = 0; i < dbsize; i++) {
- if ((name_matches(db[i], name, namelen) &&
- !fb_try_mode(var, info, &db[i], bpp)))
- return 1;
- if (res_specified && res_matches(db[i], xres, yres)) {
+ if (name_matches(db[i], name, namelen) ||
+ (res_specified && res_matches(db[i], xres, yres))) {
if(!fb_try_mode(var, info, &db[i], bpp)) {
if(!refresh_specified || db[i].refresh == refresh)
return 1;
* @var: pointer to struct fb_var_screeninfo
*/
void fb_var_to_videomode(struct fb_videomode *mode,
- struct fb_var_screeninfo *var)
+ const struct fb_var_screeninfo *var)
{
u32 pixclock, hfreq, htotal, vtotal;
* @mode: pointer to struct fb_videomode
*/
void fb_videomode_to_var(struct fb_var_screeninfo *var,
- struct fb_videomode *mode)
+ const struct fb_videomode *mode)
{
var->xres = mode->xres;
var->yres = mode->yres;
+ var->xres_virtual = mode->xres;
+ var->yres_virtual = mode->yres;
+ var->xoffset = 0;
+ var->yoffset = 0;
var->pixclock = mode->pixclock;
var->left_margin = mode->left_margin;
- var->hsync_len = mode->hsync_len;
- var->vsync_len = mode->vsync_len;
var->right_margin = mode->right_margin;
var->upper_margin = mode->upper_margin;
var->lower_margin = mode->lower_margin;
+ var->hsync_len = mode->hsync_len;
+ var->vsync_len = mode->vsync_len;
var->sync = mode->sync;
var->vmode = mode->vmode & FB_VMODE_MASK;
}
* RETURNS:
* 1 if equal, 0 if not
*/
-int fb_mode_is_equal(struct fb_videomode *mode1,
- struct fb_videomode *mode2)
+int fb_mode_is_equal(const struct fb_videomode *mode1,
+ const struct fb_videomode *mode2)
{
return (mode1->xres == mode2->xres &&
mode1->yres == mode2->yres &&
* var->xres and var->yres. If more than 1 videomode is found, will return
* the videomode with the highest refresh rate
*/
-struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
- struct list_head *head)
+const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
+ struct list_head *head)
{
struct list_head *pos;
struct fb_modelist *modelist;
if (diff > d) {
diff = d;
best = mode;
- } else if (diff == d && mode->refresh > best->refresh)
- best = mode;
+ } else if (diff == d && best &&
+ mode->refresh > best->refresh)
+ best = mode;
}
}
return best;
* If more than 1 videomode is found, will return the videomode with
* the closest refresh rate.
*/
-struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode,
- struct list_head *head)
+const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
+ struct list_head *head)
{
struct list_head *pos;
struct fb_modelist *modelist;
* RETURNS:
* struct fb_videomode, NULL if none found
*/
-struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
- struct list_head *head)
+const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
+ struct list_head *head)
{
struct list_head *pos;
struct fb_modelist *modelist;
* NOTES:
* Will only add unmatched mode entries
*/
-int fb_add_videomode(struct fb_videomode *mode, struct list_head *head)
+int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head)
{
struct list_head *pos;
struct fb_modelist *modelist;
* NOTES:
* Will remove all matching mode entries
*/
-void fb_delete_videomode(struct fb_videomode *mode, struct list_head *head)
+void fb_delete_videomode(const struct fb_videomode *mode,
+ struct list_head *head)
{
struct list_head *pos, *n;
struct fb_modelist *modelist;
* @num: number of entries in array
* @head: struct list_head of modelist
*/
-void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
+void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
struct list_head *head)
{
int i;
}
}
+const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
+ struct list_head *head)
+{
+ struct list_head *pos;
+ struct fb_modelist *modelist;
+ const struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
+ int first = 0;
+
+ if (!head->prev || !head->next || list_empty(head))
+ goto finished;
+
+ /* get the first detailed mode and the very first mode */
+ list_for_each(pos, head) {
+ modelist = list_entry(pos, struct fb_modelist, list);
+ m = &modelist->mode;
+
+ if (!first) {
+ m1 = m;
+ first = 1;
+ }
+
+ if (m->flag & FB_MODE_IS_FIRST) {
+ md = m;
+ break;
+ }
+ }
+
+ /* first detailed timing is preferred */
+ if (specs->misc & FB_MISC_1ST_DETAIL) {
+ best = md;
+ goto finished;
+ }
+
+ /* find best mode based on display width and height */
+ if (specs->max_x && specs->max_y) {
+ struct fb_var_screeninfo var;
+
+ memset(&var, 0, sizeof(struct fb_var_screeninfo));
+ var.xres = (specs->max_x * 7200)/254;
+ var.yres = (specs->max_y * 7200)/254;
+ m = fb_find_best_mode(&var, head);
+ if (m) {
+ best = m;
+ goto finished;
+ }
+ }
+
+ /* use first detailed mode */
+ if (md) {
+ best = md;
+ goto finished;
+ }
+
+ /* last resort, use the very first mode */
+ best = m1;
+finished:
+ return best;
+}
+EXPORT_SYMBOL(fb_find_best_display);
+
EXPORT_SYMBOL(fb_videomode_to_var);
EXPORT_SYMBOL(fb_var_to_videomode);
EXPORT_SYMBOL(fb_mode_is_equal);
EXPORT_SYMBOL(fb_add_videomode);
-EXPORT_SYMBOL(fb_delete_videomode);
-EXPORT_SYMBOL(fb_destroy_modelist);
EXPORT_SYMBOL(fb_match_mode);
EXPORT_SYMBOL(fb_find_best_mode);
EXPORT_SYMBOL(fb_find_nearest_mode);