Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 003cfc0c authored by Antonino A. Daplas's avatar Antonino A. Daplas Committed by Linus Torvalds
Browse files

[PATCH] fbdev: Add helper to get an appropriate initial mode



Add new helper, fb_find_best_display(), which will search the modelist for the
best mode for the attached display.  This requires an EDID block that is
converted to struct fb_monspecs and a private modelist.  The search will be
done in this manner:

- if 1st detailed timing is preferred, use that
- else if dimensions of the display are known, use that to estimate xres and
- else if modelist has detailed timings, use the first detailed timing
- else, use the very first entry from the modelist

Signed-off-by: default avatarAntonino Daplas <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 14c8102f
Loading
Loading
Loading
Loading
+60 −0
Original line number Original line Diff line number Diff line
@@ -944,6 +944,66 @@ void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
	}
	}
}
}


struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
					  struct list_head *head)
{
	struct list_head *pos;
	struct fb_modelist *modelist;
	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_videomode_to_var);
EXPORT_SYMBOL(fb_var_to_videomode);
EXPORT_SYMBOL(fb_var_to_videomode);
EXPORT_SYMBOL(fb_mode_is_equal);
EXPORT_SYMBOL(fb_mode_is_equal);
+2 −0
Original line number Original line Diff line number Diff line
@@ -902,6 +902,8 @@ extern struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode,
extern void fb_destroy_modelist(struct list_head *head);
extern void fb_destroy_modelist(struct list_head *head);
extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
				     struct list_head *head);
				     struct list_head *head);
extern struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
						 struct list_head *head);


/* drivers/video/fbcmap.c */
/* drivers/video/fbcmap.c */
extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);