summaryrefslogtreecommitdiff
path: root/drivers/video/sm501.c
blob: cafaae5f31a548929ec8773908661441b1454d00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/*
 * (C) Copyright 2002
 * Stäubli Faverges - <www.staubli.com>
 * Pierre AUBERT  p.aubert@staubli.com
 *
 * (C) Copyright 2005
 * Martin Krause TQ-Systems GmbH martin.krause@tqs.de
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

/*
 * Basic video support for SMI SM501 "Voyager" graphic controller
 */

#include <common.h>

#include <asm/io.h>
#include <video_fb.h>
#include <sm501.h>

#define read8(ptrReg)                \
    *(volatile unsigned char *)(sm501.isaBase + ptrReg)

#define write8(ptrReg,value) \
    *(volatile unsigned char *)(sm501.isaBase + ptrReg) = value

#define read16(ptrReg) \
    (*(volatile unsigned short *)(sm501.isaBase + ptrReg))

#define write16(ptrReg,value) \
    (*(volatile unsigned short *)(sm501.isaBase + ptrReg) = value)

#define read32(ptrReg) \
    (*(volatile unsigned int *)(sm501.isaBase + ptrReg))

#define write32(ptrReg, value) \
    (*(volatile unsigned int *)(sm501.isaBase + ptrReg) = value)

GraphicDevice sm501;

void write_be32(int off, unsigned int val)
{
	out_be32((unsigned __iomem *)(sm501.isaBase + off), val);
}

void write_le32(int off, unsigned int val)
{
	out_le32((unsigned __iomem *)(sm501.isaBase + off), val);
}

void (*write_reg32)(int off, unsigned int val) = write_be32;

/*-----------------------------------------------------------------------------
 * SmiSetRegs --
 *-----------------------------------------------------------------------------
 */
static void SmiSetRegs (void)
{
	/*
	 * The content of the chipset register depends on the board (clocks,
	 * ...)
	 */
	const SMI_REGS *preg = board_get_regs ();
	while (preg->Index) {
		write_reg32 (preg->Index, preg->Value);
		/*
		 * Insert a delay between
		 */
		udelay (1000);
		preg ++;
	}
}

#ifdef CONFIG_VIDEO_SM501_PCI
static struct pci_device_id sm501_pci_tbl[] = {
	{ PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_501 },
	{}
};
#endif

/*
 * We do not enforce board code to provide empty/unused
 * functions for this driver and define weak default
 * functions here.
 */
unsigned int __board_video_init (void)
{
	return 0;
}

unsigned int board_video_init (void)
			__attribute__((weak, alias("__board_video_init")));

unsigned int __board_video_get_fb (void)
{
	return 0;
}

unsigned int board_video_get_fb (void)
			__attribute__((weak, alias("__board_video_get_fb")));

void __board_validate_screen (unsigned int base)
{
}

void board_validate_screen (unsigned int base)
			__attribute__((weak, alias("__board_validate_screen")));

/*-----------------------------------------------------------------------------
 * video_hw_init --
 *-----------------------------------------------------------------------------
 */
void *video_hw_init (void)
{
#ifdef CONFIG_VIDEO_SM501_PCI
	unsigned int pci_mem_base, pci_mmio_base;
	unsigned int id;
	unsigned short device_id;
	pci_dev_t devbusfn;
	int mem;
#endif
	unsigned int *vm, i;

	memset (&sm501, 0, sizeof (GraphicDevice));

#ifdef CONFIG_VIDEO_SM501_PCI
	printf("Video: ");

	/* Look for SM501/SM502 chips */
	devbusfn = pci_find_devices(sm501_pci_tbl, 0);
	if (devbusfn < 0) {
		printf ("PCI Controller not found.\n");
		goto not_pci;
	}

	/* Setup */
	pci_write_config_dword (devbusfn, PCI_COMMAND,
				(PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
	pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
	pci_read_config_dword (devbusfn, PCI_REVISION_ID, &id);
	pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
	pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_1, &pci_mmio_base);
	sm501.frameAdrs = pci_mem_to_phys (devbusfn, pci_mem_base);
	sm501.isaBase = pci_mem_to_phys (devbusfn, pci_mmio_base);

	if (sm501.isaBase)
		write_reg32 = write_le32;

	mem = in_le32 ((unsigned __iomem *)(sm501.isaBase + 0x10));
	mem = (mem & 0x0000e000) >> 13;
	switch (mem) {
	case 1:
		mem = 8;
		break;
	case 2:
		mem = 16;
		break;
	case 3:
		mem = 32;
		break;
	case 4:
		mem = 64;
		break;
	case 5:
		mem = 2;
		break;
	case 0:
	default:
		mem = 4;
	}
	printf ("PCI SM50%d %d MB\n", ((id & 0xff) == 0xC0) ? 2 : 1, mem);
not_pci:
#endif
	/*
	 * Initialization of the access to the graphic chipset Retreive base
	 * address of the chipset (see board/RPXClassic/eccx.c)
	 */
	if (!sm501.isaBase) {
		sm501.isaBase = board_video_init ();
		if (!sm501.isaBase)
			return NULL;
	}

	if (!sm501.frameAdrs) {
		sm501.frameAdrs = board_video_get_fb ();
		if (!sm501.frameAdrs)
			return NULL;
	}

	sm501.winSizeX = board_get_width ();
	sm501.winSizeY = board_get_height ();

#if defined(CONFIG_VIDEO_SM501_8BPP)
	sm501.gdfIndex = GDF__8BIT_INDEX;
	sm501.gdfBytesPP = 1;

#elif defined(CONFIG_VIDEO_SM501_16BPP)
	sm501.gdfIndex = GDF_16BIT_565RGB;
	sm501.gdfBytesPP = 2;

#elif defined(CONFIG_VIDEO_SM501_32BPP)
	sm501.gdfIndex = GDF_32BIT_X888RGB;
	sm501.gdfBytesPP = 4;
#else
#error Unsupported SM501 BPP
#endif

	sm501.memSize = sm501.winSizeX * sm501.winSizeY * sm501.gdfBytesPP;

	/* Load Smi registers */
	SmiSetRegs ();

	/* (see board/RPXClassic/RPXClassic.c) */
	board_validate_screen (sm501.isaBase);

	/* Clear video memory */
	i = sm501.memSize/4;
	vm = (unsigned int *)sm501.frameAdrs;
	while(i--)
		*vm++ = 0;

	return (&sm501);
}