pandora/video: enable REGEN
[pandora-u-boot.git] / board / pandora / video.c
1 #include <common.h>
2 #include <asm/io.h>
3 #include <lcd.h>
4 #include <twl4030.h>
5 #include <asm/arch/dss.h>
6 #include <asm/arch/sys_proto.h>
7 #include <asm/gpio.h>
8
9 #ifdef CONFIG_LCD
10 #include "logo.h"
11
12 #define TWL_INTBR_PMBR1 0x92
13 #define GPIODATADIR1    0x9b
14 #define SETGPIODATAOUT1 0xa4
15
16 static const struct panel_config panel_cfg = {
17         .timing_h       = 0x0d504300, /* Horizantal timing */
18         .timing_v       = 0x02202700, /* Vertical timing */
19         .pol_freq       = 0x00007000, /* Pol Freq */
20         .divisor        = 0x00010004, /* 36Mhz Pixel Clock */
21         .lcd_size       = 0x01df031f, /* 800x480 */
22         .panel_type     = 0x01, /* TFT */
23         .data_lines     = 0x03, /* 24 Bit RGB */
24         .load_mode      = 0x02, /* Frame Mode */
25         .panel_color    = 0,
26 };
27
28 /*
29  * Hacky DSS/LCD initialization code
30  */
31
32 static void dss_lcd_init(uint base_addr)
33 {
34         u32 l, div, dpll4;
35
36         l = readl(0x48004d44);
37         dpll4 = 26 * ((l >> 8) & 0xfff) / ((l & 0x7f) + 1);
38         if (get_cpu_family() == CPU_OMAP36XX)
39                 dpll4 /= 2;
40
41         /* find and write dpll4 m4 divisor */
42         l = dpll4 / 4; /* / panel_cfg.divisor */
43         for (div = 2; l / div > 36; div++)
44                 ;
45
46         /* program CM_CLKSEL_DSS m4 divisor */
47         l = readl(0x48004e40);
48         writel((l & ~0x3f) | div, 0x48004e40);
49
50         omap3_dss_panel_config(&panel_cfg);
51
52         writel(base_addr, 0x48050480);
53         writel(base_addr, 0x48050484);
54         writel(0x01df031f, 0x4805048c); /* graphics window size */
55         writel(0x0000008d, 0x480504a0); /* graphics format */
56
57         /* omap3_dss_enable(); */
58         l = readl(0x48050440);
59         l |= LCD_ENABLE | GO_LCD | GP_OUT0 | GP_OUT1;
60         writel(l, 0x48050440);
61 }
62
63 /* SPI stuff to set correct clock polarity in the LCD */
64 static void lcd_spi_init(void)
65 {
66         /* Enable clock for SPI1 */
67         writel(readl(0x48004A00) | (1<<18), 0x48004A00);
68         writel(readl(0x48004A10) | (1<<18), 0x48004A10);
69
70         /* Reset module, wait for reset to complete */
71         writel(0x00000002, 0x48098010);
72         while ( !(readl(0x48098014) & 1) );
73
74         /* SPI1 base address = 0x48098000 for CS0,
75          * for CS1 add 0x14 to the offset where applicable */
76         *((volatile uint *) 0x48098034) = 0x00000000; /* CS0 +8 */
77         *((volatile uint *) 0x48098048) = 0x00000000; /* CS1 +8 */
78         *((volatile uint *) 0x4809801C) = 0x00000000;
79         *((volatile uint *) 0x48098018) = 0xFFFFFFFF;
80         *((volatile uint *) 0x48098024) = 0x00000000;
81         *((volatile uint *) 0x48098028) = 0x00000000;
82         *((volatile uint *) 0x48098010) = 0x00000308;
83         *((volatile uint *) 0x48098040) = 0x020127DC;
84         *((volatile uint *) 0x48098048) = 0x00000001; /* CS1 */
85 }
86
87 static void lcd_spi_write(uint addr, uint data)
88 {
89         data &= 0xff;
90         data |= (addr << 10) | (1 << 8);
91
92         while ( !(readl(0x48098044) & (1<<1)) );        /* wait for TXS */
93
94         writel(data, 0x4809804C);
95
96         while ( !(readl(0x48098044) & (1<<1)) );        /* wait for TXS */
97         while ( !(readl(0x48098044) & (1<<2)) );        /* wait for EOT */
98 }
99
100 static void lcd_init(void)
101 {
102         DECLARE_GLOBAL_DATA_PTR;
103         u8 d;
104
105         /* make sure LCD nreset is driven low (GPIO157)
106          * (we are called before misc_init_r() which normally handles this stuff) */
107         gpio_direction_output(157, 0);
108         /* also GPIO164 should be high (some audible noise otherwise) */
109         gpio_direction_output(164, 1);
110
111         lcd_spi_init();
112
113         /* some kernels can now disable REGEN which controls the main 5V supply,
114          * LCD is connected to it on CC units. Also enable it on Rebirth as the
115          * user may want to boot the 2.6 kernel that doesn't control REGEN */
116         if (get_cpu_family() != CPU_OMAP36XX)
117                 twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x2e,
118                                      TWL4030_PM_RECEIVER_REGEN_DEV_GRP);
119
120         /* set VPLL2 to 1.8V */
121         twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x05,
122                              TWL4030_PM_RECEIVER_VPLL2_DEDICATED);
123         twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
124                              TWL4030_PM_RECEIVER_VPLL2_DEV_GRP);
125
126         /* set VAUX1 to 3.0V (LCD) */
127         twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x04,
128                              TWL4030_PM_RECEIVER_VAUX1_DEDICATED);
129         twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
130                              TWL4030_PM_RECEIVER_VAUX1_DEV_GRP);
131
132         /* Clear frame buffer */
133         memset((void *)gd->fb_base, 0, 800*480*2);
134
135         gpio_direction_output(157, 1);
136         udelay(2000); /* Need to wait at least 1ms after reset to start sending signals */
137
138         dss_lcd_init((uint)gd->fb_base);
139
140         lcd_spi_write(0x02, 0x0f);
141         writel(0, 0x48098048); /* Disable SPI1, CS1 */
142
143         /* Set GPIOs on T2 (Turn on LCD BL) */
144         twl4030_i2c_read_u8(TWL4030_CHIP_INTBR, &d, TWL_INTBR_PMBR1);
145         d &= ~0x0c; /* switch to GPIO function */
146         twl4030_i2c_write_u8(TWL4030_CHIP_INTBR, d, TWL_INTBR_PMBR1);
147
148         twl4030_i2c_read_u8(TWL4030_CHIP_GPIO, &d, GPIODATADIR1);
149         d |= 0x40; /* GPIO6 */
150         twl4030_i2c_write_u8(TWL4030_CHIP_GPIO, d, GPIODATADIR1);
151         twl4030_i2c_write_u8(TWL4030_CHIP_GPIO, 0x40, SETGPIODATAOUT1);
152 }
153
154 static void draw_logo(void)
155 {
156         DECLARE_GLOBAL_DATA_PTR;
157         unsigned short *dest = (void *)gd->fb_base;
158         unsigned short *logo = (unsigned short *)logo_data;
159         int i;
160
161         dest += 800 * 480/2 + 800/2;
162         dest -= 800 * logo_height/2;
163         dest -= logo_width/2;
164
165         for (i = 0; i < logo_height; i++, dest += 800, logo += logo_width)
166                 memcpy(dest, logo, logo_width * 2);
167 }
168
169 /* u-boot LCD driver support */
170 vidinfo_t panel_info = {
171         800, 480, LCD_BPP
172 };
173
174 /* vars managed by lcd.c */
175 int lcd_line_length;
176 int lcd_color_fg;
177 int lcd_color_bg;
178 void *lcd_base;
179 void *lcd_console_address;
180 short console_col;
181 short console_row;
182
183 void lcd_enable(void)
184 {
185         draw_logo();
186 }
187
188 void lcd_ctrl_init(void *lcdbase)
189 {
190         lcd_init();
191         lcd_set_flush_dcache(1);
192 }
193
194 /* Calculate fb size for VIDEOLFB_ATAG. */
195 ulong calc_fbsize(void)
196 {
197         return (panel_info.vl_col * panel_info.vl_row *
198                 NBITS(panel_info.vl_bpix) / 8);
199 }
200
201 #endif /* CONFIG_LCD */