VGA DDC (not fully tested)
[mw/milkymist.git] / software / libhal / vga.c
1 /*
2  * Milkymist VJ SoC (Software)
3  * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3 of the License.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <stdio.h>
19 #include <hw/vga.h>
20
21 #include <hal/vga.h>
22
23 /*
24  * RGB565 framebuffers.
25  * We use page flipping triple buffering as described on
26  * http://en.wikipedia.org/wiki/Triple_buffering
27  *
28  * Buffers must be aligned to the start of an FML burst
29  * which is 4x64 bits, that is, 256 bits, or 32 bytes.
30  */
31 static unsigned short int framebufferA[640*480] __attribute__((aligned(32)));
32 static unsigned short int framebufferB[640*480] __attribute__((aligned(32)));
33 static unsigned short int framebufferC[640*480] __attribute__((aligned(32)));
34
35 int vga_hres;
36 int vga_vres;
37
38 unsigned short int *vga_frontbuffer; /* < buffer currently displayed (or request sent to HW) */
39 unsigned short int *vga_backbuffer;  /* < buffer currently drawn to, never read by HW */
40 unsigned short int *vga_lastbuffer;  /* < buffer displayed just before (or HW finishing last scan) */
41
42 static int i2c_init();
43
44 void vga_init()
45 {
46         vga_hres = 640;
47         vga_vres = 480;
48         
49         vga_frontbuffer = framebufferA;
50         vga_backbuffer = framebufferB;
51         vga_lastbuffer = framebufferC;
52         
53         CSR_VGA_BASEADDRESS = (unsigned int)vga_frontbuffer;
54
55         /* by default, VGA core puts out 640x480@60Hz */
56         CSR_VGA_RESET = 0;
57
58         printf("VGA: initialized at resolution %dx%d\n", vga_hres, vga_vres);
59         printf("VGA: framebuffers at 0x%08x 0x%08x 0x%08x\n",
60                 (unsigned int)&framebufferA, (unsigned int)&framebufferB, (unsigned int)&framebufferC);
61         if(i2c_init())
62                 printf("VGA: DDC I2C bus initialized\n");
63         else
64                 printf("VGA: DDC I2C bus initialization problem\n");
65 }
66
67 void vga_disable()
68 {
69         CSR_VGA_RESET = VGA_RESET;
70 }
71
72 void vga_swap_buffers()
73 {
74         unsigned short int *p;
75
76         /*
77          * Make sure last buffer swap has been executed.
78          * Beware, DMA address registers of vgafb are incomplete
79          * (only LSBs are present) so don't compare them directly
80          * with CPU pointers.
81          */
82         while(CSR_VGA_BASEADDRESS_ACT != CSR_VGA_BASEADDRESS);
83
84         p = vga_frontbuffer;
85         vga_frontbuffer = vga_backbuffer;
86         vga_backbuffer = vga_lastbuffer;
87         vga_lastbuffer = p;
88         
89         CSR_VGA_BASEADDRESS = (unsigned int)vga_frontbuffer;
90 }
91
92 /* DDC */
93 int i2c_started;
94
95 static int i2c_init()
96 {
97         unsigned int timeout;
98
99         i2c_started = 0;
100         CSR_VGA_DDC = VGA_DDC_SDC;
101         /* Check the I2C bus is ready */
102         timeout = 1000;
103         while((timeout > 0) && (!(CSR_VGA_DDC & VGA_DDC_SDAIN))) timeout--;
104
105         return timeout;
106 }
107
108 static void i2c_delay()
109 {
110         unsigned int i;
111
112         for(i=0;i<1000;i++) __asm__("nop");
113 }
114
115 /* I2C bit-banging functions from http://en.wikipedia.org/wiki/I2c */
116 static unsigned int i2c_read_bit()
117 {
118         unsigned int bit;
119
120         /* Let the slave drive data */
121         CSR_VGA_DDC = 0;
122         i2c_delay();
123         CSR_VGA_DDC = VGA_DDC_SDC;
124         i2c_delay();
125         bit = CSR_VGA_DDC & VGA_DDC_SDAIN;
126         i2c_delay();
127         CSR_VGA_DDC = 0;
128         return bit;
129 }
130
131 static void i2c_write_bit(unsigned int bit)
132 {
133         if(bit) {
134                 CSR_VGA_DDC = VGA_DDC_SDAOE|VGA_DDC_SDAOUT;
135         } else {
136                 CSR_VGA_DDC = VGA_DDC_SDAOE;
137         }
138         i2c_delay();
139         /* Clock stretching */
140         CSR_VGA_DDC |= VGA_DDC_SDC;
141         i2c_delay();
142         CSR_VGA_DDC &= ~VGA_DDC_SDC;
143 }
144
145 static void i2c_start_cond()
146 {
147         if(i2c_started) {
148                 /* set SDA to 1 */
149                 CSR_VGA_DDC = VGA_DDC_SDAOE|VGA_DDC_SDAOUT;
150                 i2c_delay();
151                 CSR_VGA_DDC |= VGA_DDC_SDC;
152         }
153         /* SCL is high, set SDA from 1 to 0 */
154         CSR_VGA_DDC = VGA_DDC_SDAOE|VGA_DDC_SDC;
155         i2c_delay();
156         CSR_VGA_DDC = VGA_DDC_SDAOE;
157         i2c_started = 1;
158 }
159
160 static void i2c_stop_cond()
161 {
162         /* set SDA to 0 */
163         CSR_VGA_DDC = VGA_DDC_SDAOE;
164         i2c_delay();
165         /* Clock stretching */
166         CSR_VGA_DDC = VGA_DDC_SDAOE|VGA_DDC_SDC;
167         /* SCL is high, set SDA from 0 to 1 */
168         CSR_VGA_DDC = VGA_DDC_SDC;
169         i2c_delay();
170         i2c_started = 0;
171 }
172
173 static unsigned int i2c_write(unsigned char byte)
174 {
175         unsigned int bit;
176         unsigned int ack;
177
178         for(bit = 0; bit < 8; bit++) {
179                 i2c_write_bit(byte & 0x80);
180                 byte <<= 1;
181         }
182         ack = !i2c_read_bit();
183         return ack;
184 }
185
186 static unsigned char i2c_read(int ack)
187 {
188         unsigned char byte = 0;
189         unsigned int bit;
190
191         for(bit = 0; bit < 8; bit++) {
192                 byte <<= 1;
193                 byte |= i2c_read_bit();
194         }
195         i2c_write_bit(!ack);
196         return byte;
197 }
198
199 int vga_read_edid(char *buffer)
200 {
201         int i;
202
203         i2c_start_cond();
204         if(!i2c_write(0xA0)) {
205                 printf("VGA: No ack for 0xA0 address\n");
206                 return 0;
207         }
208         if(!i2c_write(0x00)) {
209                 printf("VGA: No ack for EDID offset\n");
210                 return 0;
211         }
212         i2c_start_cond();
213         if(!i2c_write(0xA1)) {
214                 printf("VGA: No ack for 0xA1 address\n");
215                 return 0;
216         }
217         
218         for(i=0;i<255;i++)
219                 buffer[i] = i2c_read(1);
220         buffer[255] = i2c_read(0);
221         i2c_stop_cond();
222
223         return 1;
224 }