MINI2440: Add a command to re-init CFI NOR
[u-boot-openmoko/mini2440.git] / board / neo1973 / common / jbt6k74.c
blobc4ba2b29295f837fb108fba47abaab78f984fa3a
1 /* u-boot driver for the tpo JBT6K74-AS LCM ASIC
3 * Copyright (C) 2006-2007 by OpenMoko, Inc.
4 * Author: Harald Welte <laforge@openmoko.org>
5 * All rights reserved.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
23 #include <common.h>
24 #include <spi.h>
25 #include <video_fb.h>
26 #include <asm/errno.h>
27 #include <s3c2410.h>
28 #include "jbt6k74.h"
30 #if 0
31 #define DEBUGP(x, args...) printf("%s: " x, __FUNCTION__, ## args);
32 #define DEBUGPC(x, args...) printf(x, ## args);
33 #else
34 #define DEBUGP(x, args...) do { } while (0)
35 #define DEBUGPC(x, args...) do { } while (0)
36 #endif
39 enum jbt_register {
40 JBT_REG_SLEEP_IN = 0x10,
41 JBT_REG_SLEEP_OUT = 0x11,
43 JBT_REG_DISPLAY_OFF = 0x28,
44 JBT_REG_DISPLAY_ON = 0x29,
46 JBT_REG_RGB_FORMAT = 0x3a,
47 JBT_REG_QUAD_RATE = 0x3b,
49 JBT_REG_POWER_ON_OFF = 0xb0,
50 JBT_REG_BOOSTER_OP = 0xb1,
51 JBT_REG_BOOSTER_MODE = 0xb2,
52 JBT_REG_BOOSTER_FREQ = 0xb3,
53 JBT_REG_OPAMP_SYSCLK = 0xb4,
54 JBT_REG_VSC_VOLTAGE = 0xb5,
55 JBT_REG_VCOM_VOLTAGE = 0xb6,
56 JBT_REG_EXT_DISPL = 0xb7,
57 JBT_REG_OUTPUT_CONTROL = 0xb8,
58 JBT_REG_DCCLK_DCEV = 0xb9,
59 JBT_REG_DISPLAY_MODE1 = 0xba,
60 JBT_REG_DISPLAY_MODE2 = 0xbb,
61 JBT_REG_DISPLAY_MODE = 0xbc,
62 JBT_REG_ASW_SLEW = 0xbd,
63 JBT_REG_DUMMY_DISPLAY = 0xbe,
64 JBT_REG_DRIVE_SYSTEM = 0xbf,
66 JBT_REG_SLEEP_OUT_FR_A = 0xc0,
67 JBT_REG_SLEEP_OUT_FR_B = 0xc1,
68 JBT_REG_SLEEP_OUT_FR_C = 0xc2,
69 JBT_REG_SLEEP_IN_LCCNT_D = 0xc3,
70 JBT_REG_SLEEP_IN_LCCNT_E = 0xc4,
71 JBT_REG_SLEEP_IN_LCCNT_F = 0xc5,
72 JBT_REG_SLEEP_IN_LCCNT_G = 0xc6,
74 JBT_REG_GAMMA1_FINE_1 = 0xc7,
75 JBT_REG_GAMMA1_FINE_2 = 0xc8,
76 JBT_REG_GAMMA1_INCLINATION = 0xc9,
77 JBT_REG_GAMMA1_BLUE_OFFSET = 0xca,
79 JBT_REG_BLANK_CONTROL = 0xcf,
80 JBT_REG_BLANK_TH_TV = 0xd0,
81 JBT_REG_CKV_ON_OFF = 0xd1,
82 JBT_REG_CKV_1_2 = 0xd2,
83 JBT_REG_OEV_TIMING = 0xd3,
84 JBT_REG_ASW_TIMING_1 = 0xd4,
85 JBT_REG_ASW_TIMING_2 = 0xd5,
87 JBT_REG_HCLOCK_VGA = 0xec,
88 JBT_REG_HCLOCK_QVGA = 0xed,
92 static const char *jbt_state_names[] = {
93 [JBT_STATE_DEEP_STANDBY] = "deep-standby",
94 [JBT_STATE_SLEEP] = "sleep",
95 [JBT_STATE_NORMAL] = "normal",
98 #ifndef CONFIG_GTA02_REVISION
100 #define GTA01_SCLK (1 << 7) /* GPG7 */
101 #define GTA01_MOSI (1 << 6) /* GPG6 */
102 #define GTA01_MISO (1 << 5) /* GPG5 */
103 #define GTA01_CS (1 << 3) /* GPG3 */
105 #define SPI_READ ((immr->GPGDAT & GTA01_MISO) != 0)
107 #define SPI_CS(bit) if (bit) gpio->GPGDAT |= GTA01_CS; \
108 else gpio->GPGDAT &= ~GTA01_CS
110 #define SPI_SDA(bit) if (bit) gpio->GPGDAT |= GTA01_MOSI; \
111 else gpio->GPGDAT &= ~GTA01_MOSI
113 #define SPI_SCL(bit) if (bit) gpio->GPGDAT |= GTA01_SCLK; \
114 else gpio->GPGDAT &= ~GTA01_SCLK
116 #else /* GTA02 */
118 extern void smedia3362_spi_cs(int);
119 extern void smedia3362_spi_sda(int);
120 extern void smedia3362_spi_scl(int);
121 extern void smedia3362_lcm_reset(int);
123 #define SPI_CS(b) smedia3362_spi_cs(b)
124 #define SPI_SDA(b) smedia3362_spi_sda(b)
125 #define SPI_SCL(b) smedia3362_spi_scl(b)
127 #endif
130 /* 150uS minimum clock cycle, we have two of this plus our other
131 * instructions */
132 #define SPI_DELAY udelay(100) /* 200uS */
135 #define JBT_TX_BUF_SIZE
136 struct jbt_info {
137 enum jbt_state state;
138 u_int16_t tx_buf[4];
139 struct spi_device *spi_dev;
142 static struct jbt_info _jbt, *jbt = &_jbt;
144 static int jbt_spi_xfer(int wordnum, int bitlen, u_int16_t *dout)
146 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
147 u_int16_t tmpdout = 0;
148 int i, j;
150 DEBUGP("spi_xfer: dout %08X wordnum %u bitlen %d\n",
151 *(uint *)dout, wordnum, bitlen);
153 SPI_CS(0);
155 for (i = 0; i < wordnum; i ++) {
156 tmpdout = dout[i];
158 for (j = 0; j < bitlen; j++) {
159 SPI_SCL(0);
160 if (tmpdout & (1 << bitlen-1)) {
161 SPI_SDA(1);
162 DEBUGPC("1");
163 } else {
164 SPI_SDA(0);
165 DEBUGPC("0");
167 SPI_DELAY;
168 SPI_SCL(1);
169 SPI_DELAY;
170 tmpdout <<= 1;
172 DEBUGPC(" ");
174 DEBUGPC("\n");
176 SPI_CS(1);
178 return 0;
181 #define JBT_COMMAND 0x000
182 #define JBT_DATA 0x100
184 static int jbt_reg_write_nodata(struct jbt_info *jbt, u_int8_t reg)
186 int rc;
188 jbt->tx_buf[0] = JBT_COMMAND | reg;
190 rc = jbt_spi_xfer(1, 9, jbt->tx_buf);
192 return rc;
196 static int jbt_reg_write(struct jbt_info *jbt, u_int8_t reg, u_int8_t data)
198 int rc;
200 jbt->tx_buf[0] = JBT_COMMAND | reg;
201 jbt->tx_buf[1] = JBT_DATA | data;
203 rc = jbt_spi_xfer(2, 9, jbt->tx_buf);
205 return rc;
208 static int jbt_reg_write16(struct jbt_info *jbt, u_int8_t reg, u_int16_t data)
210 int rc;
212 jbt->tx_buf[0] = JBT_COMMAND | reg;
213 jbt->tx_buf[1] = JBT_DATA | (data >> 8);
214 jbt->tx_buf[2] = JBT_DATA | (data & 0xff);
216 rc = jbt_spi_xfer(3, 9, jbt->tx_buf);
218 return rc;
221 static int jbt_init_regs(struct jbt_info *jbt)
223 int rc;
225 DEBUGP("entering\n");
227 rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE1, 0x01);
228 rc |= jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE2, 0x00);
229 rc |= jbt_reg_write(jbt, JBT_REG_RGB_FORMAT, 0x60);
230 rc |= jbt_reg_write(jbt, JBT_REG_DRIVE_SYSTEM, 0x10);
231 rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_OP, 0x56);
232 rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_MODE, 0x33);
233 rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_FREQ, 0x11);
234 rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_FREQ, 0x11);
235 rc |= jbt_reg_write(jbt, JBT_REG_OPAMP_SYSCLK, 0x02);
236 rc |= jbt_reg_write(jbt, JBT_REG_VSC_VOLTAGE, 0x2b);
237 rc |= jbt_reg_write(jbt, JBT_REG_VCOM_VOLTAGE, 0x40);
238 rc |= jbt_reg_write(jbt, JBT_REG_EXT_DISPL, 0x03);
239 rc |= jbt_reg_write(jbt, JBT_REG_DCCLK_DCEV, 0x04);
241 * default of 0x02 in JBT_REG_ASW_SLEW responsible for 72Hz requirement
242 * to avoid red / blue flicker
244 rc |= jbt_reg_write(jbt, JBT_REG_ASW_SLEW, 0x04);
245 rc |= jbt_reg_write(jbt, JBT_REG_DUMMY_DISPLAY, 0x00);
247 rc |= jbt_reg_write(jbt, JBT_REG_SLEEP_OUT_FR_A, 0x11);
248 rc |= jbt_reg_write(jbt, JBT_REG_SLEEP_OUT_FR_B, 0x11);
249 rc |= jbt_reg_write(jbt, JBT_REG_SLEEP_OUT_FR_C, 0x11);
250 rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_D, 0x2040);
251 rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_E, 0x60c0);
252 rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_F, 0x1020);
253 rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_G, 0x60c0);
255 rc |= jbt_reg_write16(jbt, JBT_REG_GAMMA1_FINE_1, 0x5533);
256 rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_FINE_2, 0x00);
257 rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_INCLINATION, 0x00);
258 rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_BLUE_OFFSET, 0x00);
259 rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_BLUE_OFFSET, 0x00);
261 rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_VGA, 0x1f0);
262 rc |= jbt_reg_write(jbt, JBT_REG_BLANK_CONTROL, 0x02);
263 rc |= jbt_reg_write16(jbt, JBT_REG_BLANK_TH_TV, 0x0804);
264 rc |= jbt_reg_write16(jbt, JBT_REG_BLANK_TH_TV, 0x0804);
266 rc |= jbt_reg_write(jbt, JBT_REG_CKV_ON_OFF, 0x01);
267 rc |= jbt_reg_write16(jbt, JBT_REG_CKV_1_2, 0x0000);
269 rc |= jbt_reg_write16(jbt, JBT_REG_OEV_TIMING, 0x0d0e);
270 rc |= jbt_reg_write16(jbt, JBT_REG_ASW_TIMING_1, 0x11a4);
271 rc |= jbt_reg_write(jbt, JBT_REG_ASW_TIMING_2, 0x0e);
273 #if 0
274 rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_QVGA, 0x00ff);
275 rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_QVGA, 0x00ff);
276 #endif
278 return rc;
281 static int standby_to_sleep(struct jbt_info *jbt)
283 int rc;
285 DEBUGP("entering\n");
287 /* three times command zero */
288 rc = jbt_reg_write_nodata(jbt, 0x00);
289 udelay(1000);
290 rc = jbt_reg_write_nodata(jbt, 0x00);
291 udelay(1000);
292 rc = jbt_reg_write_nodata(jbt, 0x00);
293 udelay(1000);
295 /* deep standby out */
296 rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x17);
298 return rc;
301 static int sleep_to_normal(struct jbt_info *jbt)
303 int rc;
304 DEBUGP("entering\n");
306 /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */
307 rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x80);
309 /* Quad mode off */
310 rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x00);
312 /* AVDD on, XVDD on */
313 rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x16);
315 /* Output control */
316 rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0xfff9);
318 /* Sleep mode off */
319 rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT);
321 /* at this point we have like 50% grey */
323 /* initialize register set */
324 rc |= jbt_init_regs(jbt);
325 return rc;
328 static int normal_to_sleep(struct jbt_info *jbt)
330 int rc;
331 DEBUGP("entering\n");
333 rc = jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_OFF);
334 rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0x8002);
335 rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_IN);
337 return rc;
340 static int sleep_to_standby(struct jbt_info *jbt)
342 DEBUGP("entering\n");
343 return jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x00);
346 /* frontend function */
347 int jbt6k74_enter_state(enum jbt_state new_state)
349 int rc = -EINVAL;
351 DEBUGP("entering(old_state=%u, new_state=%u)\n", jbt->state, new_state);
353 switch (jbt->state) {
354 case JBT_STATE_DEEP_STANDBY:
355 switch (new_state) {
356 case JBT_STATE_DEEP_STANDBY:
357 rc = 0;
358 break;
359 case JBT_STATE_SLEEP:
360 rc = standby_to_sleep(jbt);
361 break;
362 case JBT_STATE_NORMAL:
363 /* first transition into sleep */
364 rc = standby_to_sleep(jbt);
365 /* then transition into normal */
366 rc |= sleep_to_normal(jbt);
367 break;
369 break;
370 case JBT_STATE_SLEEP:
371 switch (new_state) {
372 case JBT_STATE_SLEEP:
373 rc = 0;
374 break;
375 case JBT_STATE_DEEP_STANDBY:
376 rc = sleep_to_standby(jbt);
377 break;
378 case JBT_STATE_NORMAL:
379 rc = sleep_to_normal(jbt);
380 break;
382 break;
383 case JBT_STATE_NORMAL:
384 switch (new_state) {
385 case JBT_STATE_NORMAL:
386 rc = 0;
387 break;
388 case JBT_STATE_DEEP_STANDBY:
389 /* first transition into sleep */
390 rc = normal_to_sleep(jbt);
391 /* then transition into deep standby */
392 rc |= sleep_to_standby(jbt);
393 break;
394 case JBT_STATE_SLEEP:
395 rc = normal_to_sleep(jbt);
396 break;
398 break;
401 return rc;
404 int jbt6k74_display_onoff(int on)
406 DEBUGP("entering\n");
407 if (on)
408 return jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_ON);
409 else
410 return jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_OFF);
413 int jbt6k74_init(void)
415 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
417 #ifndef CONFIG_GTA02_REVISION
418 /* initialize SPI for GPIO bitbang */
419 gpio->GPGCON &= 0xffff033f;
420 gpio->GPGCON |= 0x00005440;
422 /* get LCM out of reset */
423 gpio->GPCDAT |= (1 << 6);
424 #else /* GTA02 */
425 smedia3362_lcm_reset(1);
426 #endif
427 /* according to data sheet: wait 50ms (Tpos of LCM). However, 50ms
428 * seems unreliable with later LCM batches, increasing to 90ms */
429 udelay(90000);
431 return 0;
434 void board_video_init(GraphicDevice *pGD)
436 S3C24X0_LCD * const lcd = S3C24X0_GetBase_LCD();
438 lcd->LCDCON1 = 0x00000178; /* CLKVAL=1, BPPMODE=16bpp, TFT, ENVID=0 */
440 lcd->LCDCON2 = 0x019fc3c1;
441 lcd->LCDCON3 = 0x0039df67;
442 lcd->LCDCON4 = 0x00000007;
443 lcd->LCDCON5 = 0x0001cf09;
444 lcd->LPCSEL = 0x00000000;