drm/i915: use current mode if the size matches the preferred mode 22/22222/3
authorKristian Høgsberg <hoegsberg@gmail.com>
Tue, 25 Feb 2014 22:33:09 +0000 (14:33 -0800)
committerJin Song <jin.kyu.song@linux.intel.com>
Fri, 30 May 2014 03:15:49 +0000 (20:15 -0700)
The BIOS may set a native mode that doesn't quite match the preferred
mode timings.  It should be ok to use however if it uses the same size,
so try to avoid a mode set in that case.

Signed-off-by: Kristian Høgsberg <hoegsberg@gmail.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Change-Id: I8b6fecd1522013dfbd1ae975ac6c6557522348e2

drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/i915/intel_fbdev.c
include/drm/drm_crtc.h

index b073315..7d2dda4 100644 (file)
@@ -894,6 +894,14 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
 }
 EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);
 
+bool drm_mode_same_size(const struct drm_display_mode *mode1,
+                       const struct drm_display_mode *mode2)
+{
+       return mode1->vdisplay == mode2->vdisplay &&
+               mode1->hdisplay == mode2->hdisplay;
+}
+EXPORT_SYMBOL(drm_mode_same_size);
+
 /**
  * drm_mode_validate_size - make sure modes adhere to size constraints
  * @dev: DRM device
index fb70f5e..8421b91 100644 (file)
@@ -324,31 +324,30 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
                /* go for command line mode first */
                modes[i] = drm_pick_cmdline_mode(fb_conn, width, height);
 
-               /* try for preferred next */
+               /* try for preferred next or match current */
                if (!modes[i]) {
+                       struct drm_display_mode *preferred;
+
                        DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
                                      fb_conn->connector->base.id);
-                       modes[i] = drm_has_preferred_mode(fb_conn, width,
-                                                         height);
-               }
-
-               /* last resort: use current mode */
-               if (!modes[i]) {
-                       /*
-                        * IMPORTANT: We want to use the adjusted mode (i.e.
-                        * after the panel fitter upscaling) as the initial
-                        * config, not the input mode, which is what crtc->mode
-                        * usually contains. But since our current fastboot
-                        * code puts a mode derived from the post-pfit timings
-                        * into crtc->mode this works out correctly. We don't
-                        * use hwmode anywhere right now, so use it for this
-                        * since the fb helper layer wants a pointer to
-                        * something we own.
-                        */
+                       preferred = drm_has_preferred_mode(fb_conn, width,
+                                                          height);
                        intel_mode_from_pipe_config(&encoder->crtc->hwmode,
                                                    &to_intel_crtc(encoder->crtc)->config);
                        modes[i] = &encoder->crtc->hwmode;
+
+                       if (preferred &&
+                           !drm_mode_same_size(preferred, modes[i])) {
+                               DRM_DEBUG_KMS("using preferred mode %s "
+                                             "instead of current mode %s "
+                                             "on connector %d\n",
+                                             preferred->name,
+                                             modes[i]->name,
+                                             fb_conn->connector->base.id);
+                               modes[i] = preferred;
+                       }
                }
+
                crtcs[i] = new_crtc;
 
                DRM_DEBUG_KMS("connector %s on crtc %d: %s\n",
index 8f3dee0..c074759 100644 (file)
@@ -1019,6 +1019,8 @@ extern bool drm_mode_equal(const struct drm_display_mode *mode1, const struct dr
 extern bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2);
 extern int drm_mode_width(const struct drm_display_mode *mode);
 extern int drm_mode_height(const struct drm_display_mode *mode);
+extern bool drm_mode_same_size(const struct drm_display_mode *mode1,
+                              const struct drm_display_mode *mode2);
 
 /* for us by fb module */
 extern struct drm_display_mode *drm_mode_create(struct drm_device *dev);