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

Commit dc891fab authored by Tomi Valkeinen's avatar Tomi Valkeinen
Browse files

OMAPFB: find best mode from edid



Use the new read_edid() function to get EDID information from the
display (when available), and use the information to use a suitable mode
at initialization time.

Hot-plug is not yet supported, so the timings selected at init time will
stay even if the monitor would be changed.

Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
parent fcca7194
Loading
Loading
Loading
Loading
+99 −10
Original line number Original line Diff line number Diff line
@@ -2276,6 +2276,87 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
	return r;
	return r;
}
}


static void fb_videomode_to_omap_timings(struct fb_videomode *m,
		struct omap_video_timings *t)
{
	t->x_res = m->xres;
	t->y_res = m->yres;
	t->pixel_clock = PICOS2KHZ(m->pixclock);
	t->hsw = m->hsync_len;
	t->hfp = m->right_margin;
	t->hbp = m->left_margin;
	t->vsw = m->vsync_len;
	t->vfp = m->lower_margin;
	t->vbp = m->upper_margin;
}

static int omapfb_find_best_mode(struct omap_dss_device *display,
		struct omap_video_timings *timings)
{
	struct fb_monspecs *specs;
	u8 *edid;
	int r, i, best_xres, best_idx, len;

	if (!display->driver->read_edid)
		return -ENODEV;

	len = 0x80 * 2;
	edid = kmalloc(len, GFP_KERNEL);

	r = display->driver->read_edid(display, edid, len);
	if (r < 0)
		goto err1;

	specs = kzalloc(sizeof(*specs), GFP_KERNEL);

	fb_edid_to_monspecs(edid, specs);

	if (edid[126] > 0)
		fb_edid_add_monspecs(edid + 0x80, specs);

	best_xres = 0;
	best_idx = -1;

	for (i = 0; i < specs->modedb_len; ++i) {
		struct fb_videomode *m;
		struct omap_video_timings t;

		m = &specs->modedb[i];

		if (m->pixclock == 0)
			continue;

		/* skip repeated pixel modes */
		if (m->xres == 2880 || m->xres == 1440)
			continue;

		fb_videomode_to_omap_timings(m, &t);

		r = display->driver->check_timings(display, &t);
		if (r == 0 && best_xres < m->xres) {
			best_xres = m->xres;
			best_idx = i;
		}
	}

	if (best_xres == 0) {
		r = -ENOENT;
		goto err2;
	}

	fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings);

	r = 0;

err2:
	fb_destroy_modedb(specs->modedb);
	kfree(specs);
err1:
	kfree(edid);

	return r;
}

static int omapfb_init_display(struct omapfb2_device *fbdev,
static int omapfb_init_display(struct omapfb2_device *fbdev,
		struct omap_dss_device *dssdev)
		struct omap_dss_device *dssdev)
{
{
@@ -2404,9 +2485,27 @@ static int omapfb_probe(struct platform_device *pdev)
	for (i = 0; i < fbdev->num_managers; i++)
	for (i = 0; i < fbdev->num_managers; i++)
		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
		fbdev->managers[i] = omap_dss_get_overlay_manager(i);


	/* gfx overlay should be the default one. find a display
	 * connected to that, and use it as default display */
	ovl = omap_dss_get_overlay(0);
	if (ovl->manager && ovl->manager->device) {
		def_display = ovl->manager->device;
	} else {
		dev_warn(&pdev->dev, "cannot find default display\n");
		def_display = NULL;
	}

	if (def_mode && strlen(def_mode) > 0) {
	if (def_mode && strlen(def_mode) > 0) {
		if (omapfb_parse_def_modes(fbdev))
		if (omapfb_parse_def_modes(fbdev))
			dev_warn(&pdev->dev, "cannot parse default modes\n");
			dev_warn(&pdev->dev, "cannot parse default modes\n");
	} else if (def_display && def_display->driver->set_timings &&
			def_display->driver->check_timings) {
		struct omap_video_timings t;

		r = omapfb_find_best_mode(def_display, &t);

		if (r == 0)
			def_display->driver->set_timings(def_display, &t);
	}
	}


	r = omapfb_create_framebuffers(fbdev);
	r = omapfb_create_framebuffers(fbdev);
@@ -2423,16 +2522,6 @@ static int omapfb_probe(struct platform_device *pdev)


	DBG("mgr->apply'ed\n");
	DBG("mgr->apply'ed\n");


	/* gfx overlay should be the default one. find a display
	 * connected to that, and use it as default display */
	ovl = omap_dss_get_overlay(0);
	if (ovl->manager && ovl->manager->device) {
		def_display = ovl->manager->device;
	} else {
		dev_warn(&pdev->dev, "cannot find default display\n");
		def_display = NULL;
	}

	if (def_display) {
	if (def_display) {
		r = omapfb_init_display(fbdev, def_display);
		r = omapfb_init_display(fbdev, def_display);
		if (r) {
		if (r) {