LCD/DSS2 support
[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
6 #ifdef CONFIG_LCD
7
8 #define TWL_INTBR_PMBR1 0x92
9 #define GPIODATADIR1    0x9b
10 #define SETGPIODATAOUT1 0xa4
11
12 /*
13  * Hacky DSS/LCD initialization code
14  */
15
16 static void dss_lcd_init(uint base_addr)
17 {
18         *((volatile uint *) 0x48004D44) = 0x0001b00c; /* DPLL4 multiplier/divider (CM_CLKSEL2_PLL) */
19         *((volatile uint *) 0x48004E40) = 0x0000100c; /* DSS clock divisors */
20         *((volatile uint *) 0x48004D00) = 0x00370037; /* control DPLL3/4 (CM_CLKEN_PLL) */
21
22         *((volatile uint *) 0x48050010) = 0x00000003;
23         while ( !(*((volatile uint *) 0x48050014) & 1) ); /* wait for reset to finish */
24
25         *((volatile uint *) 0x48050410) = 0x00002015;
26         *((volatile uint *) 0x48050444) = 0x00000004;
27         *((volatile uint *) 0x48050464) = 0x0d504300; /* horizontal timing */
28         *((volatile uint *) 0x48050468) = 0x02202700; /* vertical timing */
29         *((volatile uint *) 0x4805046c) = 0x00007000; /* polarities */
30
31         *((volatile uint *) 0x48050470) = 0x00010002;
32
33         *((volatile uint *) 0x4805047c) = 0x01df031f; /* display size */
34         *((volatile uint *) 0x48050480) = base_addr;
35         *((volatile uint *) 0x48050484) = base_addr;
36         *((volatile uint *) 0x4805048c) = 0x01df031f;
37         *((volatile uint *) 0x480504a0) = 0x0000008d;
38         *((volatile uint *) 0x480504a4) = 0x03c00200;
39
40         *((volatile uint *) 0x48050440) = 0x00018329;
41         while (*((volatile uint *) 0x48050440) & (1<<5)); /* wait for GOLCD */
42         *((volatile uint *) 0x48050440) = 0x00018329;
43 }
44
45 /* SPI stuff to set correct clock polarity in the LCD */
46 static void lcd_spi_init(void)
47 {
48         /* Enable clock for SPI1 */
49         writel(readl(0x48004A00) | (1<<18), 0x48004A00);
50         writel(readl(0x48004A10) | (1<<18), 0x48004A10);
51
52         /* Reset module, wait for reset to complete */
53         writel(0x00000002, 0x48098010);
54         while ( !(readl(0x48098014) & 1) );
55
56         /* SPI1 base address = 0x48098000 for CS0,
57          * for CS1 add 0x14 to the offset where applicable */
58         *((volatile uint *) 0x48098034) = 0x00000000; /* CS0 +8 */
59         *((volatile uint *) 0x48098048) = 0x00000000; /* CS1 +8 */
60         *((volatile uint *) 0x4809801C) = 0x00000000;
61         *((volatile uint *) 0x48098018) = 0xFFFFFFFF;
62         *((volatile uint *) 0x48098024) = 0x00000000;
63         *((volatile uint *) 0x48098028) = 0x00000000;
64         *((volatile uint *) 0x48098010) = 0x00000308;
65         *((volatile uint *) 0x48098040) = 0x020127DC;
66         *((volatile uint *) 0x48098048) = 0x00000001; /* CS1 */
67 }
68
69 static void lcd_spi_write(uint addr, uint data)
70 {
71         data &= 0xff;
72         data |= (addr << 10) | (1 << 8);
73
74         while ( !(readl(0x48098044) & (1<<1)) );        /* wait for TXS */
75
76         writel(data, 0x4809804C);
77
78         while ( !(readl(0x48098044) & (1<<1)) );        /* wait for TXS */
79         while ( !(readl(0x48098044) & (1<<2)) );        /* wait for EOT */
80 }
81
82 static void lcd_init(void)
83 {
84         DECLARE_GLOBAL_DATA_PTR;
85         u8 d;
86
87         /* make sure LCD nreset is driven low (GPIO157)
88          * (we are called before misc_init_r() which normally handles this stuff) */
89         writel(0x20000000, 0x49056090);
90         writel(readl(0x49056034) & ~0x20000000, 0x49056034);
91         /* also GPIO164 (some audible noise otherwise) */
92         writel(0x10, 0x49058094);
93         writel(readl(0x49058034) & ~0x10, 0x49058034);
94
95         lcd_spi_init();
96
97         /* set VPLL2 to 1.8V */
98         twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x05,
99                              TWL4030_PM_RECEIVER_VPLL2_DEDICATED);
100         twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
101                              TWL4030_PM_RECEIVER_VPLL2_DEV_GRP);
102
103         /* set VAUX1 to 3.0V (LCD) */
104         twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x04,
105                              TWL4030_PM_RECEIVER_VAUX1_DEDICATED);
106         twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
107                              TWL4030_PM_RECEIVER_VAUX1_DEV_GRP);
108
109         /* Clear frame buffer */
110         memset((void *)gd->fb_base, 0, 800*480*2);
111
112         writel(0x20000000, 0x49056094); /* Bring LCD out of reset (157) */
113         udelay(2000); /* Need to wait at least 1ms after reset to start sending signals */
114
115         dss_lcd_init((uint)gd->fb_base);
116
117         lcd_spi_write(0x02, 0x0f);
118         writel(0, 0x48098048); /* Disable SPI1, CS1 */
119
120         /* Set GPIOs on T2 (Turn on LCD BL) */
121         twl4030_i2c_read_u8(TWL4030_CHIP_INTBR, &d, TWL_INTBR_PMBR1);
122         d &= ~0x0c; /* switch to GPIO function */
123         twl4030_i2c_write_u8(TWL4030_CHIP_INTBR, d, TWL_INTBR_PMBR1);
124
125         twl4030_i2c_read_u8(TWL4030_CHIP_GPIO, &d, GPIODATADIR1);
126         d |= 0x40; /* GPIO6 */
127         twl4030_i2c_write_u8(TWL4030_CHIP_GPIO, d, GPIODATADIR1);
128         twl4030_i2c_write_u8(TWL4030_CHIP_GPIO, 0x40, SETGPIODATAOUT1);
129 }
130
131 /* u-boot LCD driver support */
132 vidinfo_t panel_info = {
133         800, 480, LCD_BPP
134 };
135
136 /* vars managed by lcd.c */
137 int lcd_line_length;
138 int lcd_color_fg;
139 int lcd_color_bg;
140 void *lcd_base;
141 void *lcd_console_address;
142 short console_col;
143 short console_row;
144
145 void lcd_enable(void)
146 {
147 }
148
149 void lcd_ctrl_init(void *lcdbase)
150 {
151         lcd_init();
152 }
153
154 /* Calculate fb size for VIDEOLFB_ATAG. */
155 ulong calc_fbsize(void)
156 {
157         return (panel_info.vl_col * panel_info.vl_row *
158                 NBITS(panel_info.vl_bpix) / 8);
159 }
160
161 #endif /* CONFIG_LCD */