1 /*
2 * (C) Copyright 2001-2004
3 * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
4 *
5 * (C) Copyright 2005
6 * Stefan Roese, DENX Software Engineering, sr@denx.de.
7 *
8 * (C) Copyright 2006-2007
9 * Matthias Fuchs, esd GmbH, matthias.fuchs@esd-electronics.com
10 *
11 * (C) Copyright 2009-2010
12 * Max Tretene, ACube Systems Srl. mtretene@acube-systems.com.
13 *
14 * See file CREDITS for list of people who contributed to this
15 * project.
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License as
19 * published by the Free Software Foundation; either version 2 of
20 * the License, or (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30 * MA 02111-1307 USA
31 */
32
33 #include <common.h>
34 #include <asm/processor.h>
35 #include <command.h>
36 #include <malloc.h>
37 #include <pci.h>
38 #include <video_fb.h>
39 #include <sm501.h>
40
41 #ifdef CONFIG_VIDEO_SM502
42
43 DECLARE_GLOBAL_DATA_PTR;
44
45 #define SWAP32(x) ((((x) & 0x000000ff) << 24) | (((x) & 0x0000ff00) << 8)|\
46 (((x) & 0x00ff0000) >> 8) | (((x) & 0xff000000) >> 24) )
47
48 #ifdef CONFIG_VIDEO_SM501_8BPP
49 #define BPP 8
50 #endif
51
52 #define read8(ptrReg) \
53 *(volatile unsigned char *)(sm501.isaBase + ptrReg)
54
55 #define write8(ptrReg,value) \
56 *(volatile unsigned char *)(sm501.isaBase + ptrReg) = value
57
58 #define read16(ptrReg) \
59 (*(volatile unsigned short *)(sm501.isaBase + ptrReg))
60
61 #define write16(ptrReg,value) \
62 (*(volatile unsigned short *)(sm501.isaBase + ptrReg) = value)
63
64 #define read32(ptrReg) \
65 (*(volatile unsigned int *)(sm501.isaBase + ptrReg))
66
67 #define write32(ptrReg, value) \
68 (*(volatile unsigned int *)(sm501.isaBase + ptrReg) = value)
69
70 GraphicDevice sm501;
71
72 #define DISPLAY_WIDTH 640
73 #define DISPLAY_HEIGHT 480
74
75 static const SMI_REGS init_regs_640x480[] = {
76 {0x00004, SWAP32(0x00000000)},
77 /* clocks for pm0... */
78 {0x00040, SWAP32(0x0002184f)},
79 {0x00044, SWAP32(0x091a0a01)}, /* 24 MHz pixclk */
80 {0x00054, SWAP32(0x00000000)},
81 /* clocks for pm1... */
82 {0x00048, SWAP32(0x0002184f)},
83 {0x0004C, SWAP32(0x091a0a01)},
84 {0x00054, SWAP32(0x00000001)},
85 /* panel control regs... */
86 {0x80004, SWAP32(0xc428bb17)},
87 {0x8000C, SWAP32(0x00000000)},
88 {0x80010, SWAP32(0x02800280)},
89 {0x80014, SWAP32(0x02800000)},
90 {0x80018, SWAP32(0x01e00000)},
91 {0x8001C, SWAP32(0x00000000)},
92 {0x80020, SWAP32(0x01e00280)},
93 {0x80024, SWAP32(0x02fa027f)},
94 {0x80028, SWAP32(0x004a0280)},
95 {0x8002C, SWAP32(0x020c01df)},
96 {0x80030, SWAP32(0x000201e7)},
97 {0x80200, SWAP32(0x00010000)},
98 {0x00008, SWAP32(0x20000000)}, /* gpio29 is pwm0, LED_PWM */
99 {0x0000C, SWAP32(0x3f000000)}, /* gpio56 - gpio61 as flat panel data pins */
100 {0x10020, SWAP32(0x25725728)}, /* 20 kHz pwm0, 50 % duty cycle, disabled */
101 {0x80000, SWAP32(0x0f013104)}, /* panel display control: 8 bit indexed mode */
102 {0x800F0, SWAP32(0x00000000)}, /* hardware sprite off */
103 {0x80040, SWAP32(0x00000000)}, /* video layer off */
104 /* Drawing Engine... */
105 /* Contrary to what said in the datasheet the Drawing Engine registers */
106 /* are NOT initialized to ZERO at power-up, this lead to strange visual */
107 /* bugs under Linux and AmigaOS4.1 for example */
108 {0x100000, 0},
109 {0x100004, 0},
110 {0x100008, 0},
111 {0x10000c, 0},
112 {0x100010, 0},
113 {0x100014, 0},
114 {0x100018, 0},
115 {0x10001c, 0},
116 {0x100020, 0},
117 {0x100024, 0},
118 {0x100028, 0},
119 {0x10002c, 0},
120 {0x100030, 0},
121 {0x100034, 0},
122 {0x100038, 0},
123 {0x10003c, 0},
124 {0x100040, 0},
125 {0x100044, 0},
126 {0x100048, 0},
127 {0x10004c, 0},
128 {0x100050, 0},
129 {0, 0}
130 };
131
132 /*
133 * Returns SM501 register base address. First thing called in the driver.
134 */
board_video_init(void)135 unsigned int board_video_init (void)
136 {
137 pci_dev_t devbusfn;
138 u32 addr;
139
140 /*
141 * Is SM501 connected (ppc221/ppc231)?
142 */
143 devbusfn = pci_find_device(PCI_VENDOR_SM, PCI_DEVICE_SM501, 0);
144 if (devbusfn != -1) {
145 pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, (u32 *)&addr);
146 return (addr & 0xfffffffe);
147 }
148
149 return 0;
150 }
151
152 /*
153 * Returns SM501 framebuffer address
154 */
board_video_get_fb(void)155 unsigned int board_video_get_fb (void)
156 {
157 pci_dev_t devbusfn;
158 u32 addr;
159
160 /*
161 * Is SM501 connected (ppc221/ppc231)?
162 */
163 devbusfn = pci_find_device(PCI_VENDOR_SM, PCI_DEVICE_SM501, 0);
164 if (devbusfn != -1) {
165 pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, (u32 *)&addr);
166 addr &= 0xfffffffe;
167 #ifdef CONFIG_VIDEO_SM501_FBMEM_OFFSET
168 addr += CONFIG_VIDEO_SM501_FBMEM_OFFSET;
169 #endif
170 return addr;
171 }
172
173 return 0;
174 }
175
176 /*
177 * Called after initializing the SM501 and before clearing the screen.
178 */
board_validate_screen(unsigned int base)179 void board_validate_screen (unsigned int base)
180 {
181 }
182
183 /*
184 * Return a pointer to the initialization sequence.
185 */
board_get_regs(void)186 const SMI_REGS *board_get_regs (void)
187 {
188 return init_regs_640x480;
189 }
190
board_get_width(void)191 int board_get_width (void)
192 {
193 return 640;
194 }
195
board_get_height(void)196 int board_get_height (void)
197 {
198 return 480;
199 }
200
201 /*-----------------------------------------------------------------------------
202 * SmiSetRegs --
203 *-----------------------------------------------------------------------------
204 */
SmiSetRegs(void)205 static void SmiSetRegs (void)
206 {
207 /*
208 * The content of the chipset register depends on the board (clocks,
209 * ...)
210 */
211 const SMI_REGS *preg = board_get_regs ();
212 while (preg->Index) {
213 write32 (preg->Index, preg->Value);
214 /*
215 * Insert a delay between
216 */
217 udelay (1000);
218 preg ++;
219 }
220 }
221
222 /*-----------------------------------------------------------------------------
223 * video_hw_init --
224 *-----------------------------------------------------------------------------
225 */
video_hw_init(void)226 void *video_hw_init (void)
227 {
228 unsigned int *vm, i;
229
230 memset (&sm501, 0, sizeof (GraphicDevice));
231
232 /*
233 * Initialization of the access to the graphic chipset Retreive base
234 * address of the chipset (see board/RPXClassic/eccx.c)
235 */
236 if ((sm501.isaBase = board_video_init ()) == 0) {
237 return (NULL);
238 }
239
240 if ((sm501.frameAdrs = board_video_get_fb ()) == 0) {
241 return (NULL);
242 }
243
244 sm501.winSizeX = board_get_width ();
245 sm501.winSizeY = board_get_height ();
246
247 #if defined(CONFIG_VIDEO_SM501_8BPP)
248 sm501.gdfIndex = GDF__8BIT_INDEX;
249 sm501.gdfBytesPP = 1;
250
251 #elif defined(CONFIG_VIDEO_SM501_16BPP)
252 sm501.gdfIndex = GDF_16BIT_565RGB;
253 sm501.gdfBytesPP = 2;
254
255 #elif defined(CONFIG_VIDEO_SM501_32BPP)
256 sm501.gdfIndex = GDF_32BIT_X888RGB;
257 sm501.gdfBytesPP = 4;
258 #else
259 #error Unsupported SM501 BPP
260 #endif
261
262 sm501.memSize = sm501.winSizeX * sm501.winSizeY * sm501.gdfBytesPP;
263
264 /* Load Smi registers */
265 SmiSetRegs ();
266
267 /* (see board/RPXClassic/RPXClassic.c) */
268 board_validate_screen (sm501.isaBase);
269
270 /* Clear video memory */
271 i = sm501.memSize/4;
272 vm = (unsigned int *)sm501.frameAdrs;
273 while(i--)
274 *vm++ = 0;
275
276 return (&sm501);
277 }
278
279 /*-----------------------------------------------------------------------------
280 * video_set_lut --
281 *-----------------------------------------------------------------------------
282 */
video_set_lut(unsigned int index,unsigned char r,unsigned char g,unsigned char b)283 void video_set_lut (
284 unsigned int index, /* color number */
285 unsigned char r, /* red */
286 unsigned char g, /* green */
287 unsigned char b /* blue */
288 )
289 {
290 unsigned long value = 0;
291 //unsigned char tt = index;
292
293 value = (r << 16) | (g << 8) | b;
294
295 // using a gray palette
296 //value = (tt << 16) | (tt << 8) | tt;
297
298 write32 ((index*4) + 0x80400, SWAP32(value));
299 }
300
301 #endif /* CONFIG_VIDEO_SM502 */
302