aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/via/via-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/via/via-core.c')
-rw-r--r--drivers/video/via/via-core.c185
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 */
33static 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 */
41static 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 */
49static 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 */
162static 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
186static void __devexit via_pci_teardown_mmio(struct viafb_dev *vdev)
187{
188 iounmap(vdev->fbmem);
189 iounmap(vdev->engine_mmio);
190}
191
26 192
27static int __devinit via_pci_probe(struct pci_dev *pdev, 193static 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
50out_i2c: 226out_i2c:
51 viafb_delete_i2c_busses(); 227 viafb_delete_i2c_busses();
228out_teardown:
229 via_pci_teardown_mmio(&global_dev);
52out_disable: 230out_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