Merge branch 'agust@denx.de' of git://git.denx.de/u-boot-staging
[platform/kernel/u-boot.git] / drivers / video / sm501.c
1 /*
2  * (C) Copyright 2002
3  * Stäubli Faverges - <www.staubli.com>
4  * Pierre AUBERT  p.aubert@staubli.com
5  *
6  * (C) Copyright 2005
7  * Martin Krause TQ-Systems GmbH martin.krause@tqs.de
8  *
9  * SPDX-License-Identifier:     GPL-2.0+
10  */
11
12 /*
13  * Basic video support for SMI SM501 "Voyager" graphic controller
14  */
15
16 #include <common.h>
17
18 #include <asm/io.h>
19 #include <video_fb.h>
20 #include <sm501.h>
21
22 #define read8(ptrReg)                \
23     *(volatile unsigned char *)(sm501.isaBase + ptrReg)
24
25 #define write8(ptrReg,value) \
26     *(volatile unsigned char *)(sm501.isaBase + ptrReg) = value
27
28 #define read16(ptrReg) \
29     (*(volatile unsigned short *)(sm501.isaBase + ptrReg))
30
31 #define write16(ptrReg,value) \
32     (*(volatile unsigned short *)(sm501.isaBase + ptrReg) = value)
33
34 #define read32(ptrReg) \
35     (*(volatile unsigned int *)(sm501.isaBase + ptrReg))
36
37 #define write32(ptrReg, value) \
38     (*(volatile unsigned int *)(sm501.isaBase + ptrReg) = value)
39
40 GraphicDevice sm501;
41
42 void write_be32(int off, unsigned int val)
43 {
44         out_be32((unsigned __iomem *)(sm501.isaBase + off), val);
45 }
46
47 void write_le32(int off, unsigned int val)
48 {
49         out_le32((unsigned __iomem *)(sm501.isaBase + off), val);
50 }
51
52 void (*write_reg32)(int off, unsigned int val) = write_be32;
53
54 /*-----------------------------------------------------------------------------
55  * SmiSetRegs --
56  *-----------------------------------------------------------------------------
57  */
58 static void SmiSetRegs (void)
59 {
60         /*
61          * The content of the chipset register depends on the board (clocks,
62          * ...)
63          */
64         const SMI_REGS *preg = board_get_regs ();
65         while (preg->Index) {
66                 write_reg32 (preg->Index, preg->Value);
67                 /*
68                  * Insert a delay between
69                  */
70                 udelay (1000);
71                 preg ++;
72         }
73 }
74
75 #ifdef CONFIG_VIDEO_SM501_PCI
76 static struct pci_device_id sm501_pci_tbl[] = {
77         { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_501 },
78         {}
79 };
80 #endif
81
82 /*
83  * We do not enforce board code to provide empty/unused
84  * functions for this driver and define weak default
85  * functions here.
86  */
87 unsigned int __board_video_init (void)
88 {
89         return 0;
90 }
91
92 unsigned int board_video_init (void)
93                         __attribute__((weak, alias("__board_video_init")));
94
95 unsigned int __board_video_get_fb (void)
96 {
97         return 0;
98 }
99
100 unsigned int board_video_get_fb (void)
101                         __attribute__((weak, alias("__board_video_get_fb")));
102
103 void __board_validate_screen (unsigned int base)
104 {
105 }
106
107 void board_validate_screen (unsigned int base)
108                         __attribute__((weak, alias("__board_validate_screen")));
109
110 /*-----------------------------------------------------------------------------
111  * video_hw_init --
112  *-----------------------------------------------------------------------------
113  */
114 void *video_hw_init (void)
115 {
116 #ifdef CONFIG_VIDEO_SM501_PCI
117         unsigned int pci_mem_base, pci_mmio_base;
118         unsigned int id;
119         unsigned short device_id;
120         pci_dev_t devbusfn;
121         int mem;
122 #endif
123         unsigned int *vm, i;
124
125         memset (&sm501, 0, sizeof (GraphicDevice));
126
127 #ifdef CONFIG_VIDEO_SM501_PCI
128         printf("Video: ");
129
130         /* Look for SM501/SM502 chips */
131         devbusfn = pci_find_devices(sm501_pci_tbl, 0);
132         if (devbusfn < 0) {
133                 printf ("PCI Controller not found.\n");
134                 goto not_pci;
135         }
136
137         /* Setup */
138         pci_write_config_dword (devbusfn, PCI_COMMAND,
139                                 (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
140         pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
141         pci_read_config_dword (devbusfn, PCI_REVISION_ID, &id);
142         pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
143         pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_1, &pci_mmio_base);
144         sm501.frameAdrs = pci_mem_to_phys (devbusfn, pci_mem_base);
145         sm501.isaBase = pci_mem_to_phys (devbusfn, pci_mmio_base);
146
147         if (sm501.isaBase)
148                 write_reg32 = write_le32;
149
150         mem = in_le32 ((unsigned __iomem *)(sm501.isaBase + 0x10));
151         mem = (mem & 0x0000e000) >> 13;
152         switch (mem) {
153         case 1:
154                 mem = 8;
155                 break;
156         case 2:
157                 mem = 16;
158                 break;
159         case 3:
160                 mem = 32;
161                 break;
162         case 4:
163                 mem = 64;
164                 break;
165         case 5:
166                 mem = 2;
167                 break;
168         case 0:
169         default:
170                 mem = 4;
171         }
172         printf ("PCI SM50%d %d MB\n", ((id & 0xff) == 0xC0) ? 2 : 1, mem);
173 not_pci:
174 #endif
175         /*
176          * Initialization of the access to the graphic chipset Retreive base
177          * address of the chipset (see board/RPXClassic/eccx.c)
178          */
179         if (!sm501.isaBase) {
180                 sm501.isaBase = board_video_init ();
181                 if (!sm501.isaBase)
182                         return NULL;
183         }
184
185         if (!sm501.frameAdrs) {
186                 sm501.frameAdrs = board_video_get_fb ();
187                 if (!sm501.frameAdrs)
188                         return NULL;
189         }
190
191         sm501.winSizeX = board_get_width ();
192         sm501.winSizeY = board_get_height ();
193
194 #if defined(CONFIG_VIDEO_SM501_8BPP)
195         sm501.gdfIndex = GDF__8BIT_INDEX;
196         sm501.gdfBytesPP = 1;
197
198 #elif defined(CONFIG_VIDEO_SM501_16BPP)
199         sm501.gdfIndex = GDF_16BIT_565RGB;
200         sm501.gdfBytesPP = 2;
201
202 #elif defined(CONFIG_VIDEO_SM501_32BPP)
203         sm501.gdfIndex = GDF_32BIT_X888RGB;
204         sm501.gdfBytesPP = 4;
205 #else
206 #error Unsupported SM501 BPP
207 #endif
208
209         sm501.memSize = sm501.winSizeX * sm501.winSizeY * sm501.gdfBytesPP;
210
211         /* Load Smi registers */
212         SmiSetRegs ();
213
214         /* (see board/RPXClassic/RPXClassic.c) */
215         board_validate_screen (sm501.isaBase);
216
217         /* Clear video memory */
218         i = sm501.memSize/4;
219         vm = (unsigned int *)sm501.frameAdrs;
220         while(i--)
221                 *vm++ = 0;
222
223         return (&sm501);
224 }