fbdev: sh_mobile_hdmi: support hot-plugging of different HDMI / DVI displays

With this patch hot-plugging of an HDMI or a DVI monitor can select a different
video mode and reconfigure the LCDC and HDMI controllers accordingly. Due to a
lack of a standard API to inform framebuffer users of a changed video mode, the
framebuffer configuration is preserved regardless of a specific mode, selected
for the monitor. As described in a previous patch, this leads to smaller
framebuffers being displayed on larger monitors or a part of a larger
framebuffer being displayed on a smaller resolution monitor.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 946a810..b4a8786 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -944,6 +944,7 @@
 	struct sh_mobile_lcdc_chan *ch = info->par;
 	struct sh_mobile_lcdc_board_cfg	*board_cfg = &ch->cfg.board_cfg;
 	struct fb_var_screeninfo *var;
+	int ret;
 
 	if (&ch->lcdc->notifier != nb)
 		return NOTIFY_DONE;
@@ -958,6 +959,7 @@
 			module_put(board_cfg->owner);
 		}
 		pm_runtime_put(info->device);
+		sh_mobile_lcdc_stop(ch->lcdc);
 		break;
 	case FB_EVENT_RESUME:
 		var = &info->var;
@@ -968,31 +970,9 @@
 			module_put(board_cfg->owner);
 		}
 
-		/* Check if the new display is not in our modelist */
-		if (ch->info->modelist.next &&
-		    !fb_match_mode(var, &ch->info->modelist)) {
-			struct fb_videomode mode;
-			int ret;
-
-			/* Can we handle this display? */
-			if (var->xres > ch->cfg.lcd_cfg[0].xres ||
-			    var->yres > ch->cfg.lcd_cfg[0].yres)
-				/*
-				 * LCDC resume failed, no need to continue with
-				 * the notifier chain
-				 */
-				return notifier_from_errno(-ENOMEM);
-
-			/* Add to the modelist */
-			fb_var_to_videomode(&mode, var);
-			ret = fb_add_videomode(&mode, &ch->info->modelist);
-			if (ret < 0)
-				return notifier_from_errno(ret);
-		}
-
-		pm_runtime_get_sync(info->device);
-
-		sh_mobile_lcdc_geometry(ch);
+		ret = sh_mobile_lcdc_start(ch->lcdc);
+		if (!ret)
+			pm_runtime_get_sync(info->device);
 	}
 
 	return NOTIFY_OK;
@@ -1181,6 +1161,7 @@
 			}
 		}
 
+		fb_videomode_to_modelist(ch->cfg.lcd_cfg, ch->cfg.num_cfg, &info->modelist);
 		error = register_framebuffer(info);
 		if (error < 0)
 			goto err1;