diff options
Diffstat (limited to 'drivers/video/via/via-core.c')
-rw-r--r-- | drivers/video/via/via-core.c | 185 |
1 files changed, 182 insertions, 3 deletions
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index e7201470cf35..b77cd5c2fc96 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c | |||
@@ -7,9 +7,12 @@ | |||
7 | /* | 7 | /* |
8 | * Core code for the Via multifunction framebuffer device. | 8 | * Core code for the Via multifunction framebuffer device. |
9 | */ | 9 | */ |
10 | #include "via-core.h" | ||
11 | #include "via_i2c.h" | ||
12 | #include "global.h" | ||
13 | |||
10 | #include <linux/module.h> | 14 | #include <linux/module.h> |
11 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
12 | #include "global.h" /* Includes everything under the sun */ | ||
13 | 16 | ||
14 | /* | 17 | /* |
15 | * The default port config. | 18 | * The default port config. |
@@ -23,6 +26,169 @@ static struct via_port_cfg adap_configs[] = { | |||
23 | { 0, 0, 0, 0 } | 26 | { 0, 0, 0, 0 } |
24 | }; | 27 | }; |
25 | 28 | ||
29 | /* | ||
30 | * We currently only support one viafb device (will there ever be | ||
31 | * more than one?), so just declare it globally here. | ||
32 | */ | ||
33 | static struct viafb_dev global_dev; | ||
34 | |||
35 | |||
36 | /* | ||
37 | * Figure out how big our framebuffer memory is. Kind of ugly, | ||
38 | * but evidently we can't trust the information found in the | ||
39 | * fbdev configuration area. | ||
40 | */ | ||
41 | static u16 via_function3[] = { | ||
42 | CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3, | ||
43 | CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3, | ||
44 | P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, | ||
45 | }; | ||
46 | |||
47 | /* Get the BIOS-configured framebuffer size from PCI configuration space | ||
48 | * of function 3 in the respective chipset */ | ||
49 | static int viafb_get_fb_size_from_pci(int chip_type) | ||
50 | { | ||
51 | int i; | ||
52 | u8 offset = 0; | ||
53 | u32 FBSize; | ||
54 | u32 VideoMemSize; | ||
55 | |||
56 | /* search for the "FUNCTION3" device in this chipset */ | ||
57 | for (i = 0; i < ARRAY_SIZE(via_function3); i++) { | ||
58 | struct pci_dev *pdev; | ||
59 | |||
60 | pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i], | ||
61 | NULL); | ||
62 | if (!pdev) | ||
63 | continue; | ||
64 | |||
65 | DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device); | ||
66 | |||
67 | switch (pdev->device) { | ||
68 | case CLE266_FUNCTION3: | ||
69 | case KM400_FUNCTION3: | ||
70 | offset = 0xE0; | ||
71 | break; | ||
72 | case CN400_FUNCTION3: | ||
73 | case CN700_FUNCTION3: | ||
74 | case CX700_FUNCTION3: | ||
75 | case KM800_FUNCTION3: | ||
76 | case KM890_FUNCTION3: | ||
77 | case P4M890_FUNCTION3: | ||
78 | case P4M900_FUNCTION3: | ||
79 | case VX800_FUNCTION3: | ||
80 | case VX855_FUNCTION3: | ||
81 | /*case CN750_FUNCTION3: */ | ||
82 | offset = 0xA0; | ||
83 | break; | ||
84 | } | ||
85 | |||
86 | if (!offset) | ||
87 | break; | ||
88 | |||
89 | pci_read_config_dword(pdev, offset, &FBSize); | ||
90 | pci_dev_put(pdev); | ||
91 | } | ||
92 | |||
93 | if (!offset) { | ||
94 | printk(KERN_ERR "cannot determine framebuffer size\n"); | ||
95 | return -EIO; | ||
96 | } | ||
97 | |||
98 | FBSize = FBSize & 0x00007000; | ||
99 | DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize); | ||
100 | |||
101 | if (chip_type < UNICHROME_CX700) { | ||
102 | switch (FBSize) { | ||
103 | case 0x00004000: | ||
104 | VideoMemSize = (16 << 20); /*16M */ | ||
105 | break; | ||
106 | |||
107 | case 0x00005000: | ||
108 | VideoMemSize = (32 << 20); /*32M */ | ||
109 | break; | ||
110 | |||
111 | case 0x00006000: | ||
112 | VideoMemSize = (64 << 20); /*64M */ | ||
113 | break; | ||
114 | |||
115 | default: | ||
116 | VideoMemSize = (32 << 20); /*32M */ | ||
117 | break; | ||
118 | } | ||
119 | } else { | ||
120 | switch (FBSize) { | ||
121 | case 0x00001000: | ||
122 | VideoMemSize = (8 << 20); /*8M */ | ||
123 | break; | ||
124 | |||
125 | case 0x00002000: | ||
126 | VideoMemSize = (16 << 20); /*16M */ | ||
127 | break; | ||
128 | |||
129 | case 0x00003000: | ||
130 | VideoMemSize = (32 << 20); /*32M */ | ||
131 | break; | ||
132 | |||
133 | case 0x00004000: | ||
134 | VideoMemSize = (64 << 20); /*64M */ | ||
135 | break; | ||
136 | |||
137 | case 0x00005000: | ||
138 | VideoMemSize = (128 << 20); /*128M */ | ||
139 | break; | ||
140 | |||
141 | case 0x00006000: | ||
142 | VideoMemSize = (256 << 20); /*256M */ | ||
143 | break; | ||
144 | |||
145 | case 0x00007000: /* Only on VX855/875 */ | ||
146 | VideoMemSize = (512 << 20); /*512M */ | ||
147 | break; | ||
148 | |||
149 | default: | ||
150 | VideoMemSize = (32 << 20); /*32M */ | ||
151 | break; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | return VideoMemSize; | ||
156 | } | ||
157 | |||
158 | |||
159 | /* | ||
160 | * Figure out and map our MMIO regions. | ||
161 | */ | ||
162 | static int __devinit via_pci_setup_mmio(struct viafb_dev *vdev) | ||
163 | { | ||
164 | /* | ||
165 | * Hook up to the device registers. | ||
166 | */ | ||
167 | vdev->engine_start = pci_resource_start(vdev->pdev, 1); | ||
168 | vdev->engine_len = pci_resource_len(vdev->pdev, 1); | ||
169 | /* If this fails, others will notice later */ | ||
170 | vdev->engine_mmio = ioremap_nocache(vdev->engine_start, | ||
171 | vdev->engine_len); | ||
172 | |||
173 | /* | ||
174 | * Likewise with I/O memory. | ||
175 | */ | ||
176 | vdev->fbmem_start = pci_resource_start(vdev->pdev, 0); | ||
177 | vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type); | ||
178 | if (vdev->fbmem_len < 0) | ||
179 | return vdev->fbmem_len; | ||
180 | vdev->fbmem = ioremap_nocache(vdev->fbmem_start, vdev->fbmem_len); | ||
181 | if (vdev->fbmem == NULL) | ||
182 | return -ENOMEM; | ||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static void __devexit via_pci_teardown_mmio(struct viafb_dev *vdev) | ||
187 | { | ||
188 | iounmap(vdev->fbmem); | ||
189 | iounmap(vdev->engine_mmio); | ||
190 | } | ||
191 | |||
26 | 192 | ||
27 | static int __devinit via_pci_probe(struct pci_dev *pdev, | 193 | static int __devinit via_pci_probe(struct pci_dev *pdev, |
28 | const struct pci_device_id *ent) | 194 | const struct pci_device_id *ent) |
@@ -33,22 +199,34 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, | |||
33 | if (ret) | 199 | if (ret) |
34 | return ret; | 200 | return ret; |
35 | /* | 201 | /* |
202 | * Global device initialization. | ||
203 | */ | ||
204 | memset(&global_dev, 0, sizeof(global_dev)); | ||
205 | global_dev.pdev = pdev; | ||
206 | global_dev.chip_type = ent->driver_data; | ||
207 | spin_lock_init(&global_dev.reg_lock); | ||
208 | ret = via_pci_setup_mmio(&global_dev); | ||
209 | if (ret) | ||
210 | goto out_disable; | ||
211 | /* | ||
36 | * Create the I2C busses. Bailing out on failure seems extreme, | 212 | * Create the I2C busses. Bailing out on failure seems extreme, |
37 | * but that's what the code did before. | 213 | * but that's what the code did before. |
38 | */ | 214 | */ |
39 | ret = viafb_create_i2c_busses(adap_configs); | 215 | ret = viafb_create_i2c_busses(adap_configs); |
40 | if (ret) | 216 | if (ret) |
41 | goto out_disable; | 217 | goto out_teardown; |
42 | /* | 218 | /* |
43 | * Set up the framebuffer. | 219 | * Set up the framebuffer. |
44 | */ | 220 | */ |
45 | ret = via_fb_pci_probe(pdev, ent); | 221 | ret = via_fb_pci_probe(&global_dev); |
46 | if (ret) | 222 | if (ret) |
47 | goto out_i2c; | 223 | goto out_i2c; |
48 | return 0; | 224 | return 0; |
49 | 225 | ||
50 | out_i2c: | 226 | out_i2c: |
51 | viafb_delete_i2c_busses(); | 227 | viafb_delete_i2c_busses(); |
228 | out_teardown: | ||
229 | via_pci_teardown_mmio(&global_dev); | ||
52 | out_disable: | 230 | out_disable: |
53 | pci_disable_device(pdev); | 231 | pci_disable_device(pdev); |
54 | return ret; | 232 | return ret; |
@@ -58,6 +236,7 @@ static void __devexit via_pci_remove(struct pci_dev *pdev) | |||
58 | { | 236 | { |
59 | viafb_delete_i2c_busses(); | 237 | viafb_delete_i2c_busses(); |
60 | via_fb_pci_remove(pdev); | 238 | via_fb_pci_remove(pdev); |
239 | via_pci_teardown_mmio(&global_dev); | ||
61 | pci_disable_device(pdev); | 240 | pci_disable_device(pdev); |
62 | } | 241 | } |
63 | 242 | ||