Merge branch 'master' of git://git.denx.de/u-boot-video
[platform/kernel/u-boot.git] / drivers / video / sed13806.c
1 /*
2  * (C) Copyright 2002
3  * Stäubli Faverges - <www.staubli.com>
4  * Pierre AUBERT  p.aubert@staubli.com
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  */
24 /* Video support for Epson SED13806 chipset                                  */
25
26 #include <common.h>
27
28 #include <video_fb.h>
29 #include <sed13806.h>
30
31 #define readByte(ptrReg)                \
32     *(volatile unsigned char *)(sed13806.isaBase + ptrReg)
33
34 #define writeByte(ptrReg,value) \
35     *(volatile unsigned char *)(sed13806.isaBase + ptrReg) = value
36
37 #ifdef CONFIG_TOTAL5200
38 #define writeWord(ptrReg,value) \
39     (*(volatile unsigned short *)(sed13806.isaBase + ptrReg) = value)
40 #else
41 #define writeWord(ptrReg,value) \
42     (*(volatile unsigned short *)(sed13806.isaBase + ptrReg) = ((value >> 8 ) & 0xff) | ((value << 8) & 0xff00))
43 #endif
44
45 GraphicDevice sed13806;
46
47 /*-----------------------------------------------------------------------------
48  * EpsonSetRegs --
49  *-----------------------------------------------------------------------------
50  */
51 static void EpsonSetRegs (void)
52 {
53     /* the content of the chipset register depends on the board (clocks, ...)*/
54     const S1D_REGS *preg = board_get_regs ();
55     while (preg -> Index) {
56         writeByte (preg -> Index, preg -> Value);
57         preg ++;
58     }
59 }
60
61 /*-----------------------------------------------------------------------------
62  * video_hw_init --
63  *-----------------------------------------------------------------------------
64  */
65 void *video_hw_init (void)
66 {
67     unsigned int *vm, i;
68
69     memset (&sed13806, 0, sizeof (GraphicDevice));
70
71     /* Initialization of the access to the graphic chipset
72        Retreive base address of the chipset
73        (see board/RPXClassic/eccx.c)                                         */
74     if ((sed13806.isaBase = board_video_init ()) == 0) {
75         return (NULL);
76     }
77
78     sed13806.frameAdrs = sed13806.isaBase + FRAME_BUFFER_OFFSET;
79     sed13806.winSizeX = board_get_width ();
80     sed13806.winSizeY = board_get_height ();
81
82 #if defined(CONFIG_VIDEO_SED13806_8BPP)
83     sed13806.gdfIndex = GDF__8BIT_INDEX;
84     sed13806.gdfBytesPP = 1;
85
86 #elif defined(CONFIG_VIDEO_SED13806_16BPP)
87     sed13806.gdfIndex = GDF_16BIT_565RGB;
88     sed13806.gdfBytesPP = 2;
89
90 #else
91 #error Unsupported SED13806 BPP
92 #endif
93
94     sed13806.memSize = sed13806.winSizeX * sed13806.winSizeY * sed13806.gdfBytesPP;
95
96     /* Load SED registers                                                    */
97     EpsonSetRegs ();
98
99     /* (see board/RPXClassic/RPXClassic.c)                                   */
100     board_validate_screen (sed13806.isaBase);
101
102     /* Clear video memory */
103     i = sed13806.memSize/4;
104     vm = (unsigned int *)sed13806.frameAdrs;
105     while(i--)
106         *vm++ = 0;
107
108
109     return (&sed13806);
110 }
111 /*-----------------------------------------------------------------------------
112  * Epson_wait_idle -- Wait for hardware to become idle
113  *-----------------------------------------------------------------------------
114  */
115 static void Epson_wait_idle (void)
116 {
117     while (readByte (BLT_CTRL0) & 0x80);
118
119     /* Read a word in the BitBLT memory area to shutdown the BitBLT engine   */
120     *(volatile unsigned short *)(sed13806.isaBase + BLT_REG);
121 }
122
123 /*-----------------------------------------------------------------------------
124  * video_hw_bitblt --
125  *-----------------------------------------------------------------------------
126  */
127 void video_hw_bitblt (
128     unsigned int bpp,             /* bytes per pixel */
129     unsigned int src_x,           /* source pos x */
130     unsigned int src_y,           /* source pos y */
131     unsigned int dst_x,           /* dest pos x */
132     unsigned int dst_y,           /* dest pos y */
133     unsigned int dim_x,           /* frame width */
134     unsigned int dim_y            /* frame height */
135     )
136 {
137     register GraphicDevice *pGD = (GraphicDevice *)&sed13806;
138     unsigned long       srcAddr, dstAddr;
139     unsigned int stride = bpp * pGD -> winSizeX;
140
141     srcAddr = (src_y * stride) + (src_x * bpp);
142     dstAddr = (dst_y * stride) + (dst_x * bpp);
143
144     Epson_wait_idle ();
145
146     writeByte(BLT_ROP,0x0C);    /* source */
147     writeByte(BLT_OP,0x02);/* move blit in positive direction with ROP */
148     writeWord(BLT_MEM_OFF0, stride / 2);
149     if (pGD -> gdfIndex == GDF__8BIT_INDEX) {
150         writeByte(BLT_CTRL1,0x00);
151     }
152     else {
153         writeByte(BLT_CTRL1,0x01);
154     }
155
156     writeWord(BLT_WIDTH0,(dim_x - 1));
157     writeWord(BLT_HEIGHT0,(dim_y - 1));
158
159     /* set up blit registers                                                 */
160     writeByte(BLT_SRC_ADDR0,srcAddr);
161     writeByte(BLT_SRC_ADDR1,srcAddr>>8);
162     writeByte(BLT_SRC_ADDR2,srcAddr>>16);
163
164     writeByte(BLT_DST_ADDR0,dstAddr);
165     writeByte(BLT_DST_ADDR1,dstAddr>>8);
166     writeByte(BLT_DST_ADDR2,dstAddr>>16);
167
168     /* Engage the blt engine                                                 */
169     /* rectangular region for src and dst                                    */
170     writeByte(BLT_CTRL0,0x80);
171
172     /* wait untill current blits finished                                    */
173     Epson_wait_idle ();
174 }
175 /*-----------------------------------------------------------------------------
176  * video_hw_rectfill --
177  *-----------------------------------------------------------------------------
178  */
179 void video_hw_rectfill (
180     unsigned int bpp,             /* bytes per pixel */
181     unsigned int dst_x,           /* dest pos x */
182     unsigned int dst_y,           /* dest pos y */
183     unsigned int dim_x,           /* frame width */
184     unsigned int dim_y,           /* frame height */
185     unsigned int color            /* fill color */
186      )
187 {
188     register GraphicDevice *pGD = (GraphicDevice *)&sed13806;
189     unsigned long       dstAddr;
190     unsigned int stride = bpp * pGD -> winSizeX;
191
192     dstAddr = (dst_y * stride) + (dst_x * bpp);
193
194     Epson_wait_idle ();
195
196     /* set up blit registers                                                 */
197     writeByte(BLT_DST_ADDR0,dstAddr);
198     writeByte(BLT_DST_ADDR1,dstAddr>>8);
199     writeByte(BLT_DST_ADDR2,dstAddr>>16);
200
201     writeWord(BLT_WIDTH0,(dim_x - 1));
202     writeWord(BLT_HEIGHT0,(dim_y - 1));
203     writeWord(BLT_FGCOLOR0,color);
204
205     writeByte(BLT_OP,0x0C);  /* solid fill                                   */
206     writeWord(BLT_MEM_OFF0,stride / 2);
207
208     if (pGD -> gdfIndex == GDF__8BIT_INDEX) {
209         writeByte(BLT_CTRL1,0x00);
210     }
211     else {
212         writeByte(BLT_CTRL1,0x01);
213     }
214
215     /* Engage the blt engine                                                 */
216     /* rectangular region for src and dst                                    */
217     writeByte(BLT_CTRL0,0x80);
218
219     /* wait untill current blits finished                                    */
220     Epson_wait_idle ();
221 }
222
223 /*-----------------------------------------------------------------------------
224  * video_set_lut --
225  *-----------------------------------------------------------------------------
226  */
227 void video_set_lut (
228     unsigned int index,           /* color number */
229     unsigned char r,              /* red */
230     unsigned char g,              /* green */
231     unsigned char b               /* blue */
232     )
233 {
234     writeByte(REG_LUT_ADDR, index );
235     writeByte(REG_LUT_DATA, r);
236     writeByte(REG_LUT_DATA, g);
237     writeByte(REG_LUT_DATA, b);
238 }
239 #ifdef CONFIG_VIDEO_HW_CURSOR
240 /*-----------------------------------------------------------------------------
241  * video_set_hw_cursor --
242  *-----------------------------------------------------------------------------
243  */
244 void video_set_hw_cursor (int x, int y)
245 {
246     writeByte (LCD_CURSOR_XL, (x & 0xff));
247     writeByte (LCD_CURSOR_XM, (x >> 8));
248     writeByte (LCD_CURSOR_YL, (y & 0xff));
249     writeByte (LCD_CURSOR_YM, (y >> 8));
250 }
251
252 /*-----------------------------------------------------------------------------
253  * video_init_hw_cursor --
254  *-----------------------------------------------------------------------------
255  */
256 void video_init_hw_cursor (int font_width, int font_height)
257 {
258     volatile unsigned char *ptr;
259     unsigned char pattern;
260     int i;
261
262
263     /* Init cursor content
264        Cursor size is 64x64 pixels
265        Start of the cursor memory depends on panel type (dual panel ...)     */
266     if ((i = readByte (LCD_CURSOR_START)) == 0) {
267         ptr = (unsigned char *)(sed13806.frameAdrs + DEFAULT_VIDEO_MEMORY_SIZE - HWCURSORSIZE);
268     }
269     else {
270         ptr = (unsigned char *)(sed13806.frameAdrs + DEFAULT_VIDEO_MEMORY_SIZE - (i * 8192));
271     }
272
273     /* Fill the first line and the first empty line after cursor             */
274     for (i = 0, pattern = 0; i < 64; i++) {
275         if (i < font_width) {
276             /* Invert background                                             */
277             pattern |= 0x3;
278
279         }
280         else {
281             /* Background                                                    */
282             pattern |= 0x2;
283         }
284         if ((i & 3) == 3) {
285             *ptr = pattern;
286             *(ptr + font_height * 16) = 0xaa;
287             ptr ++;
288             pattern = 0;
289         }
290         pattern <<= 2;
291     }
292
293     /* Duplicate this line                                                   */
294     for (i = 1; i < font_height; i++) {
295         memcpy ((void *)ptr, (void *)(ptr - 16), 16);
296         ptr += 16;
297     }
298
299     for (; i < 64; i++) {
300         memcpy ((void *)(ptr + 16), (void *)ptr, 16);
301         ptr += 16;
302     }
303
304     /* Select cursor mode                                                    */
305     writeByte (LCD_CURSOR_CNTL, 1);
306 }
307 #endif