Index: linux-2.6.20.2/drivers/spi/jbt6k74.c
===================================================================
--- linux-2.6.20.2.orig/drivers/spi/jbt6k74.c	2007-03-24 01:12:12.000000000 +0100
+++ linux-2.6.20.2/drivers/spi/jbt6k74.c	2007-03-24 01:46:24.000000000 +0100
@@ -1,7 +1,8 @@
 /* Linux kernel driver for the tpo JBT6K74-AS LCM ASIC
  *
  * Copyright (C) 2006-2007 by OpenMoko, Inc.
- * Author: Harald Welte <laforge@openmoko.org>
+ * Author: Harald Welte <laforge@openmoko.org>,
+ * 		   Stefan Schmidt <stefan@openmoko.org>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -69,6 +70,7 @@
 	JBT_REG_GAMMA1_INCLINATION	= 0xc9,
 	JBT_REG_GAMMA1_BLUE_OFFSET	= 0xca,
 
+	/* VGA */
 	JBT_REG_BLANK_CONTROL		= 0xcf,
 	JBT_REG_BLANK_TH_TV		= 0xd0,
 	JBT_REG_CKV_ON_OFF		= 0xd1,
@@ -77,6 +79,15 @@
 	JBT_REG_ASW_TIMING_1		= 0xd4,
 	JBT_REG_ASW_TIMING_2		= 0xd5,
 
+	/* QVGA */
+	JBT_REG_BLANK_CONTROL_QVGA	= 0xd6,
+	JBT_REG_BLANK_TH_TV_QVGA	= 0xd7,
+	JBT_REG_CKV_ON_OFF_QVGA		= 0xd8,
+	JBT_REG_CKV_1_2_QVGA		= 0xd9,
+	JBT_REG_OEV_TIMING_QVGA		= 0xde,
+	JBT_REG_ASW_TIMING_1_QVGA	= 0xdf,
+	JBT_REG_ASW_TIMING_2_QVGA	= 0xe0,
+
 	JBT_REG_HCLOCK_VGA		= 0xec,
 	JBT_REG_HCLOCK_QVGA		= 0xed,
 
@@ -86,12 +97,14 @@
 	JBT_STATE_DEEP_STANDBY,
 	JBT_STATE_SLEEP,
 	JBT_STATE_NORMAL,
+	JBT_STATE_NORMAL_QVGA,
 };
 
 static const char *jbt_state_names[] = {
 	[JBT_STATE_DEEP_STANDBY]	= "deep-standby",
 	[JBT_STATE_SLEEP]		= "sleep",
 	[JBT_STATE_NORMAL]		= "normal",
+	[JBT_STATE_NORMAL_QVGA]		= "normal-qvga",
 };
 
 #if 1
@@ -155,7 +168,7 @@
 	return rc;
 }
 
-static int jbt_init_regs(struct jbt_info *jbt)
+static int jbt_init_regs(struct jbt_info *jbt, int qvga)
 {
 	int rc;
 
@@ -189,16 +202,32 @@
 	rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_INCLINATION, 0x00);
 	rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_BLUE_OFFSET, 0x00);
 
-	rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_VGA, 0x1f0);
-	rc |= jbt_reg_write(jbt, JBT_REG_BLANK_CONTROL, 0x02);
-	rc |= jbt_reg_write16(jbt, JBT_REG_BLANK_TH_TV, 0x0804);
-
-	rc |= jbt_reg_write(jbt, JBT_REG_CKV_ON_OFF, 0x01);
-	rc |= jbt_reg_write16(jbt, JBT_REG_CKV_1_2, 0x0000);
-
-	rc |= jbt_reg_write16(jbt, JBT_REG_OEV_TIMING, 0x0d0e);
-	rc |= jbt_reg_write16(jbt, JBT_REG_ASW_TIMING_1, 0x11a4);
-	rc |= jbt_reg_write(jbt, JBT_REG_ASW_TIMING_2, 0x0e);
+	if (!qvga) {
+		DEBUGP("entering VGA mode\n");
+		rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_VGA, 0x1f0);
+		rc |= jbt_reg_write(jbt, JBT_REG_BLANK_CONTROL, 0x02);
+		rc |= jbt_reg_write16(jbt, JBT_REG_BLANK_TH_TV, 0x0804);
+
+		rc |= jbt_reg_write(jbt, JBT_REG_CKV_ON_OFF, 0x01);
+		rc |= jbt_reg_write16(jbt, JBT_REG_CKV_1_2, 0x0000);
+
+		rc |= jbt_reg_write16(jbt, JBT_REG_OEV_TIMING, 0x0d0e);
+		rc |= jbt_reg_write16(jbt, JBT_REG_ASW_TIMING_1, 0x11a4);
+		rc |= jbt_reg_write(jbt, JBT_REG_ASW_TIMING_2, 0x0e);
+	}
+	else {
+		DEBUGP("entering QVGA mode\n");
+		rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_QVGA, 0x00ff);
+		rc |= jbt_reg_write(jbt, JBT_REG_BLANK_CONTROL_QVGA, 0x02);
+		rc |= jbt_reg_write16(jbt, JBT_REG_BLANK_TH_TV_QVGA, 0x0804);
+
+		rc |= jbt_reg_write(jbt, JBT_REG_CKV_ON_OFF_QVGA, 0x01);
+		rc |= jbt_reg_write16(jbt, JBT_REG_CKV_1_2_QVGA, 0x0008);
+
+		rc |= jbt_reg_write16(jbt, JBT_REG_OEV_TIMING_QVGA, 0x050a);
+		rc |= jbt_reg_write16(jbt, JBT_REG_ASW_TIMING_1_QVGA, 0x0a19);
+		rc |= jbt_reg_write(jbt, JBT_REG_ASW_TIMING_2_QVGA, 0x0a);
+	}
 
 	return rc;
 }
@@ -244,10 +273,35 @@
 	rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT);
 
 	/* initialize register set */
-	rc |= jbt_init_regs(jbt);
+	rc |= jbt_init_regs(jbt, 0);
 	return rc;
 }
 
+static int sleep_to_normal_qvga(struct jbt_info *jbt)
+{
+  int rc;
+  DEBUGP("entering\n");
+
+  /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */
+  rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x81);
+
+  /* Quad mode on */
+  rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x22);
+
+  /* AVDD on, XVDD on */
+  rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x16);
+
+  /* Output control */
+  rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0xfff9);
+
+  /* Sleep mode off */
+  rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT);
+
+  /* initialize register set for qvga*/
+  rc |= jbt_init_regs(jbt, 1);
+ 	return rc;
+}
+
 static int normal_to_sleep(struct jbt_info *jbt)
 {
 	int rc;
@@ -288,6 +342,12 @@
 			/* then transition into normal */
 			rc |= sleep_to_normal(jbt);
 			break;
+		case JBT_STATE_NORMAL_QVGA:
+			/* first transition into sleep */
+			rc = standby_to_sleep(jbt);
+			/* then transition into normal */
+			rc |= sleep_to_normal_qvga(jbt);
+			break;
 		}
 		break;
 	case JBT_STATE_SLEEP:
@@ -301,6 +361,9 @@
 		case JBT_STATE_NORMAL:
 			rc = sleep_to_normal(jbt);
 			break;
+		case JBT_STATE_NORMAL_QVGA:
+			rc = sleep_to_normal_qvga(jbt);
+			break;
 		}
 		break;
 	case JBT_STATE_NORMAL:
@@ -317,6 +380,42 @@
 		case JBT_STATE_SLEEP:
 			rc = normal_to_sleep(jbt);
 			break;
+		case JBT_STATE_NORMAL_QVGA:
+			/* first transition into sleep */
+			rc = normal_to_sleep(jbt);
+			/* second transition into deep standby */
+			rc |= sleep_to_standby(jbt);
+			/* third transition into sleep */
+			rc |= standby_to_sleep(jbt);
+			/* fourth transition into normal */
+			rc |= sleep_to_normal_qvga(jbt);
+			break;
+		}
+		break;
+	case JBT_STATE_NORMAL_QVGA:
+		switch (new_state) {
+		case JBT_STATE_NORMAL_QVGA:
+			rc = 0;
+			break;
+		case JBT_STATE_DEEP_STANDBY:
+			/* first transition into sleep */
+			rc = normal_to_sleep(jbt);
+			/* then transition into deep standby */
+			rc |= sleep_to_standby(jbt);
+			break;
+		case JBT_STATE_SLEEP:
+			rc = normal_to_sleep(jbt);
+			break;
+		case JBT_STATE_NORMAL:
+			/* first transition into sleep */
+			rc = normal_to_sleep(jbt);
+			/* second transition into deep standby */
+			rc |= sleep_to_standby(jbt);
+			/* third transition into sleep */
+			rc |= standby_to_sleep(jbt);
+			/* fourth transition into normal */
+			rc |= sleep_to_normal(jbt);
+			break;
 		}
 		break;
 	}
