--- a/drivers/video/gcnfb.c
+++ b/drivers/video/gcnfb.c
@@ -441,6 +441,7 @@
 
 	struct vi_tv_mode *mode;
 	struct vi_mode_timings timings;
+	int has_component_cable:1;	/* at last detection time */
 
 	struct fb_info *info;
 #ifdef CONFIG_WII_AVE_RVL
@@ -980,6 +981,16 @@
 	return vi_get_video_format(ctl) == VI_FMT_NTSC;
 }
 
+static void vi_reset_video(struct vi_ctl *ctl)
+{
+	void __iomem *io_base = ctl->io_base;
+	u16 dcr;
+
+	dcr = in_be16(io_base + VI_DCR);
+	out_be16(io_base + VI_DCR, vi_dcr_set_rst(dcr, 1));
+	out_be16(io_base + VI_DCR, vi_dcr_clear_rst(dcr));
+}
+
 /*
  * Try to determine current TV video mode.
  */
@@ -995,10 +1006,12 @@
 
 	dcr = in_be16(io_base + VI_DCR);
 
+	ctl->has_component_cable = vi_has_component_cable(ctl);
+
 	if ((force_scan == VI_SCAN_PROGRESSIVE &&
-					vi_has_component_cable(ctl)) ||
+					ctl->has_component_cable) ||
 	    (force_scan != VI_SCAN_INTERLACED &&
-					vi_has_component_cable(ctl) &&
+					ctl->has_component_cable &&
 					vi_dcr_get_nin(dcr))) {
 		/* progressive modes */
 		ntsc_idx = VI_VM_NTSC_480p;
@@ -1064,10 +1077,19 @@
 {
 	void __iomem *io_base = ctl->io_base;
 	struct vi_mode_timings *timings = &ctl->timings;
-	struct vi_tv_mode *mode = ctl->mode;
 	struct fb_var_screeninfo *var = &ctl->info->var;
 	unsigned int bytes_per_pixel = var->bits_per_pixel / 8;
+	struct vi_tv_mode *mode;
+	int has_component_cable;
 	u16 std, ppl;
+
+	/* we need to re-detect the tv mode if the cable type changes */
+	has_component_cable = vi_has_component_cable(ctl);
+	if ((ctl->has_component_cable && !has_component_cable) ||
+	    (!ctl->has_component_cable && has_component_cable))
+		vi_detect_tv_mode(ctl);
+
+	mode = ctl->mode;
 
 	out_be16(io_base + VI_DCR,
 		 vi_dcr_fmt((mode->lines == 625) ? VI_FMT_PAL : VI_FMT_NTSC) |
@@ -1409,7 +1431,6 @@
 {
 	struct i2c_client *client;
 	u8 macrovision[26];
-	int has_component;
 	u8 component, format, pal60;
 
 	if (!ctl->i2c_client)
@@ -1417,8 +1438,6 @@
 
 	client = ctl->i2c_client;
 	memset(macrovision, 0, sizeof(macrovision));
-
-	has_component = vi_has_component_cable(ctl);
 
 	/*
 	 * Magic initialization sequence borrowed from libogc.
@@ -1436,7 +1455,7 @@
 	format = 0;		/* default to NTSC */
 	if ((ctl->mode->flags & VI_VMF_PAL_COLOR) != 0)
 		format = 2;	/* PAL */
-	component = (has_component) ? 1<<5 : 0;
+	component = (ctl->has_component_cable) ? 1<<5 : 0;
 	vi_ave_out8(client, 0x01, component | format);
 
 	vi_ave_out8(client, 0x00, 0);
@@ -1457,7 +1476,7 @@
 	vi_ave_out8(client, 0x03, 1);
 
 	/* clear bit 1 otherwise red and blue get swapped  */
-	if (has_component)
+	if (ctl->has_component_cable)
 		vi_ave_out8(client, 0x62, 0);
 
 	/* PAL 480i/60 supposedly needs a "filter" */
@@ -1751,7 +1770,7 @@
 	var->nonstd = 0;	/* lies... */
 
 	/* enable non-interlaced mode if supported */
-	if (force_scan != VI_SCAN_INTERLACED && vi_has_component_cable(ctl)) {
+	if (force_scan != VI_SCAN_INTERLACED && ctl->has_component_cable) {
 		var->vmode = (mode->flags & VI_VMF_PROGRESSIVE) ?
 					FB_VMODE_NONINTERLACED :
 					FB_VMODE_INTERLACED;
@@ -1968,6 +1987,7 @@
 	spin_lock_init(&ctl->lock);
 	init_waitqueue_head(&ctl->vtrace_waitq);
 
+	vi_reset_video(ctl);
 	vi_detect_tv_mode(ctl);
 
 	/* by default, start with overscan compensation */
@@ -2068,6 +2088,19 @@
 		first_vi_ctl = NULL;
 #endif
 	framebuffer_release(info);
+	return 0;
+}
+
+static int vifb_do_shutdown(struct device *dev)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct vi_ctl *ctl = info->par;
+	void __iomem *io_base = ctl->io_base;
+
+	vi_enable_interrupts(ctl, 0);
+	vi_reset_video(ctl);
+	out_be16(io_base + VI_DCR, vi_dcr_enb(0));
+
 	return 0;
 }
 
@@ -2159,6 +2192,11 @@
 	return vifb_do_remove(&odev->dev);
 }
 
+static int vifb_of_shutdown(struct of_device *odev)
+{
+	return vifb_do_shutdown(&odev->dev);
+}
+
 
 static struct of_device_id vifb_of_match[] = {
 	{ .compatible = "nintendo,flipper-video", },
@@ -2174,6 +2212,7 @@
 	.match_table = vifb_of_match,
 	.probe = vifb_of_probe,
 	.remove = vifb_of_remove,
+	.shutdown = vifb_of_shutdown,
 };
 
 /*