MLK-14648: mxc: fix default modelist
authorRobert Chiras <robert.chiras@nxp.com>
Thu, 27 Apr 2017 10:07:21 +0000 (13:07 +0300)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:22:07 +0000 (15:22 -0500)
When EDID read fails, the mxc_hdmi driver creates a default modelist
using a hard-coded list with CEA modes.
Every time the HDMI cable is plugged-in, it will destroy the current
modelist and recreate the list. The problem comes from fbcon, which
holds reference to current mode used for each framebuffer console. When
we destroy the modelist and send the new one, if the memory for the old
mode is overwritten it will try to find another mode, close to the old
one. Since the mode could be overwritten by something else there is a
high chance that the new selected mode to be different from the old one.
If the HDMI sink does not support the selected mode, IPU will fail to
deliver frames.
Since it's wrong to advertise as supported modes the modes from a
hard-coded list, just use one mode, which comes from cmdline.

Signed-off-by: Robert Chiras <robert.chiras@nxp.com>
drivers/video/fbdev/mxc/mxc_hdmi.c

index 830d518..467fe63 100644 (file)
@@ -1830,27 +1830,35 @@ static void  mxc_hdmi_default_edid_cfg(struct mxc_hdmi *hdmi)
 
 static void  mxc_hdmi_default_modelist(struct mxc_hdmi *hdmi)
 {
-       u32 i;
-       const struct fb_videomode *mode;
+       struct fb_modelist *modelist;
+       struct fb_videomode *m;
 
        dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
 
-       /* If not EDID data read, set up default modelist  */
+       /* If no EDID data read, set up default modelist; since we don't know
+        * the supported modes of the current sink, we will use only one mode in
+        * this modelist:
+        * the default_mode set up at init (usually got from cmdline)
+        */
        dev_info(&hdmi->pdev->dev, "create default modelist\n");
 
-       console_lock();
-
-       fb_destroy_modelist(&hdmi->fbi->modelist);
+       /* If the current modelist is already default, don't re-create it*/
+       if (list_is_singular(&hdmi->fbi->modelist)) {
+               modelist = list_entry((&hdmi->fbi->modelist)->next,
+                               struct fb_modelist, list);
+               m = &modelist->mode;
+               if (fb_mode_is_equal(m, &hdmi->default_mode)) {
+                       dev_info(&hdmi->pdev->dev,
+                               "Modelist is already default, no need to re-create!\n");
+                       return;
+               }
 
-       /*Add all no interlaced CEA mode to default modelist */
-       for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
-               mode = &mxc_cea_mode[i];
-               if (!(mode->vmode & FB_VMODE_INTERLACED) && (mode->xres != 0))
-                       fb_add_videomode(mode, &hdmi->fbi->modelist);
        }
 
+       console_lock();
+       fb_destroy_modelist(&hdmi->fbi->modelist);
+       fb_add_videomode(&hdmi->default_mode, &hdmi->fbi->modelist);
        fb_new_modelist(hdmi->fbi);
-
        console_unlock();
 }