diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/Kconfig | 4 | ||||
-rw-r--r-- | drivers/video/pmag-ba-fb.c | 95 |
2 files changed, 56 insertions, 43 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 4e83f01e894e..18c22ba6e656 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -1444,8 +1444,8 @@ config FB_PMAG_AA | |||
1444 | used mainly in the MIPS-based DECstation series. | 1444 | used mainly in the MIPS-based DECstation series. |
1445 | 1445 | ||
1446 | config FB_PMAG_BA | 1446 | config FB_PMAG_BA |
1447 | bool "PMAG-BA TURBOchannel framebuffer support" | 1447 | tristate "PMAG-BA TURBOchannel framebuffer support" |
1448 | depends on (FB = y) && TC | 1448 | depends on FB && TC |
1449 | select FB_CFB_FILLRECT | 1449 | select FB_CFB_FILLRECT |
1450 | select FB_CFB_COPYAREA | 1450 | select FB_CFB_COPYAREA |
1451 | select FB_CFB_IMAGEBLIT | 1451 | select FB_CFB_IMAGEBLIT |
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index f5361cd8ccce..264d37243fad 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c | |||
@@ -15,7 +15,8 @@ | |||
15 | * Michael Engel <engel@unix-ag.org>, | 15 | * Michael Engel <engel@unix-ag.org>, |
16 | * Karsten Merker <merker@linuxtag.org> and | 16 | * Karsten Merker <merker@linuxtag.org> and |
17 | * Harald Koerfgen. | 17 | * Harald Koerfgen. |
18 | * Copyright (c) 2005 Maciej W. Rozycki | 18 | * Copyright (c) 2005, 2006 Maciej W. Rozycki |
19 | * Copyright (c) 2005 James Simmons | ||
19 | * | 20 | * |
20 | * This file is subject to the terms and conditions of the GNU General | 21 | * This file is subject to the terms and conditions of the GNU General |
21 | * Public License. See the file COPYING in the main directory of this | 22 | * Public License. See the file COPYING in the main directory of this |
@@ -28,26 +29,21 @@ | |||
28 | #include <linux/init.h> | 29 | #include <linux/init.h> |
29 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
30 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/tc.h> | ||
31 | #include <linux/types.h> | 33 | #include <linux/types.h> |
32 | 34 | ||
33 | #include <asm/io.h> | 35 | #include <asm/io.h> |
34 | #include <asm/system.h> | 36 | #include <asm/system.h> |
35 | 37 | ||
36 | #include <asm/dec/tc.h> | ||
37 | |||
38 | #include <video/pmag-ba-fb.h> | 38 | #include <video/pmag-ba-fb.h> |
39 | 39 | ||
40 | 40 | ||
41 | struct pmagbafb_par { | 41 | struct pmagbafb_par { |
42 | struct fb_info *next; | ||
43 | volatile void __iomem *mmio; | 42 | volatile void __iomem *mmio; |
44 | volatile u32 __iomem *dac; | 43 | volatile u32 __iomem *dac; |
45 | int slot; | ||
46 | }; | 44 | }; |
47 | 45 | ||
48 | 46 | ||
49 | static struct fb_info *root_pmagbafb_dev; | ||
50 | |||
51 | static struct fb_var_screeninfo pmagbafb_defined __initdata = { | 47 | static struct fb_var_screeninfo pmagbafb_defined __initdata = { |
52 | .xres = 1024, | 48 | .xres = 1024, |
53 | .yres = 864, | 49 | .yres = 864, |
@@ -145,24 +141,19 @@ static void __init pmagbafb_erase_cursor(struct fb_info *info) | |||
145 | } | 141 | } |
146 | 142 | ||
147 | 143 | ||
148 | static int __init pmagbafb_init_one(int slot) | 144 | static int __init pmagbafb_probe(struct device *dev) |
149 | { | 145 | { |
146 | struct tc_dev *tdev = to_tc_dev(dev); | ||
147 | resource_size_t start, len; | ||
150 | struct fb_info *info; | 148 | struct fb_info *info; |
151 | struct pmagbafb_par *par; | 149 | struct pmagbafb_par *par; |
152 | unsigned long base_addr; | ||
153 | 150 | ||
154 | info = framebuffer_alloc(sizeof(struct pmagbafb_par), NULL); | 151 | info = framebuffer_alloc(sizeof(struct pmagbafb_par), dev); |
155 | if (!info) | 152 | if (!info) |
156 | return -ENOMEM; | 153 | return -ENOMEM; |
157 | 154 | ||
158 | par = info->par; | 155 | par = info->par; |
159 | par->slot = slot; | 156 | dev_set_drvdata(dev, info); |
160 | claim_tc_card(par->slot); | ||
161 | |||
162 | base_addr = get_tc_base_addr(par->slot); | ||
163 | |||
164 | par->next = root_pmagbafb_dev; | ||
165 | root_pmagbafb_dev = info; | ||
166 | 157 | ||
167 | if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) | 158 | if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) |
168 | goto err_alloc; | 159 | goto err_alloc; |
@@ -172,15 +163,21 @@ static int __init pmagbafb_init_one(int slot) | |||
172 | info->var = pmagbafb_defined; | 163 | info->var = pmagbafb_defined; |
173 | info->flags = FBINFO_DEFAULT; | 164 | info->flags = FBINFO_DEFAULT; |
174 | 165 | ||
166 | /* Request the I/O MEM resource. */ | ||
167 | start = tdev->resource.start; | ||
168 | len = tdev->resource.end - start + 1; | ||
169 | if (!request_mem_region(start, len, dev->bus_id)) | ||
170 | goto err_cmap; | ||
171 | |||
175 | /* MMIO mapping setup. */ | 172 | /* MMIO mapping setup. */ |
176 | info->fix.mmio_start = base_addr; | 173 | info->fix.mmio_start = start; |
177 | par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); | 174 | par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); |
178 | if (!par->mmio) | 175 | if (!par->mmio) |
179 | goto err_cmap; | 176 | goto err_resource; |
180 | par->dac = par->mmio + PMAG_BA_BT459; | 177 | par->dac = par->mmio + PMAG_BA_BT459; |
181 | 178 | ||
182 | /* Frame buffer mapping setup. */ | 179 | /* Frame buffer mapping setup. */ |
183 | info->fix.smem_start = base_addr + PMAG_BA_FBMEM; | 180 | info->fix.smem_start = start + PMAG_BA_FBMEM; |
184 | info->screen_base = ioremap_nocache(info->fix.smem_start, | 181 | info->screen_base = ioremap_nocache(info->fix.smem_start, |
185 | info->fix.smem_len); | 182 | info->fix.smem_len); |
186 | if (!info->screen_base) | 183 | if (!info->screen_base) |
@@ -192,8 +189,10 @@ static int __init pmagbafb_init_one(int slot) | |||
192 | if (register_framebuffer(info) < 0) | 189 | if (register_framebuffer(info) < 0) |
193 | goto err_smem_map; | 190 | goto err_smem_map; |
194 | 191 | ||
195 | pr_info("fb%d: %s frame buffer device in slot %d\n", | 192 | get_device(dev); |
196 | info->node, info->fix.id, par->slot); | 193 | |
194 | pr_info("fb%d: %s frame buffer device at %s\n", | ||
195 | info->node, info->fix.id, dev->bus_id); | ||
197 | 196 | ||
198 | return 0; | 197 | return 0; |
199 | 198 | ||
@@ -204,54 +203,68 @@ err_smem_map: | |||
204 | err_mmio_map: | 203 | err_mmio_map: |
205 | iounmap(par->mmio); | 204 | iounmap(par->mmio); |
206 | 205 | ||
206 | err_resource: | ||
207 | release_mem_region(start, len); | ||
208 | |||
207 | err_cmap: | 209 | err_cmap: |
208 | fb_dealloc_cmap(&info->cmap); | 210 | fb_dealloc_cmap(&info->cmap); |
209 | 211 | ||
210 | err_alloc: | 212 | err_alloc: |
211 | root_pmagbafb_dev = par->next; | ||
212 | release_tc_card(par->slot); | ||
213 | framebuffer_release(info); | 213 | framebuffer_release(info); |
214 | return -ENXIO; | 214 | return -ENXIO; |
215 | } | 215 | } |
216 | 216 | ||
217 | static void __exit pmagbafb_exit_one(void) | 217 | static int __exit pmagbafb_remove(struct device *dev) |
218 | { | 218 | { |
219 | struct fb_info *info = root_pmagbafb_dev; | 219 | struct tc_dev *tdev = to_tc_dev(dev); |
220 | struct fb_info *info = dev_get_drvdata(dev); | ||
220 | struct pmagbafb_par *par = info->par; | 221 | struct pmagbafb_par *par = info->par; |
222 | resource_size_t start, len; | ||
221 | 223 | ||
224 | put_device(dev); | ||
222 | unregister_framebuffer(info); | 225 | unregister_framebuffer(info); |
223 | iounmap(info->screen_base); | 226 | iounmap(info->screen_base); |
224 | iounmap(par->mmio); | 227 | iounmap(par->mmio); |
228 | start = tdev->resource.start; | ||
229 | len = tdev->resource.end - start + 1; | ||
230 | release_mem_region(start, len); | ||
225 | fb_dealloc_cmap(&info->cmap); | 231 | fb_dealloc_cmap(&info->cmap); |
226 | root_pmagbafb_dev = par->next; | ||
227 | release_tc_card(par->slot); | ||
228 | framebuffer_release(info); | 232 | framebuffer_release(info); |
233 | return 0; | ||
229 | } | 234 | } |
230 | 235 | ||
231 | 236 | ||
232 | /* | 237 | /* |
233 | * Initialise the framebuffer. | 238 | * Initialize the framebuffer. |
234 | */ | 239 | */ |
240 | static const struct tc_device_id pmagbafb_tc_table[] = { | ||
241 | { "DEC ", "PMAG-BA " }, | ||
242 | { } | ||
243 | }; | ||
244 | MODULE_DEVICE_TABLE(tc, pmagbafb_tc_table); | ||
245 | |||
246 | static struct tc_driver pmagbafb_driver = { | ||
247 | .id_table = pmagbafb_tc_table, | ||
248 | .driver = { | ||
249 | .name = "pmagbafb", | ||
250 | .bus = &tc_bus_type, | ||
251 | .probe = pmagbafb_probe, | ||
252 | .remove = __exit_p(pmagbafb_remove), | ||
253 | }, | ||
254 | }; | ||
255 | |||
235 | static int __init pmagbafb_init(void) | 256 | static int __init pmagbafb_init(void) |
236 | { | 257 | { |
237 | int count = 0; | 258 | #ifndef MODULE |
238 | int slot; | ||
239 | |||
240 | if (fb_get_options("pmagbafb", NULL)) | 259 | if (fb_get_options("pmagbafb", NULL)) |
241 | return -ENXIO; | 260 | return -ENXIO; |
242 | 261 | #endif | |
243 | while ((slot = search_tc_card("PMAG-BA")) >= 0) { | 262 | return tc_register_driver(&pmagbafb_driver); |
244 | if (pmagbafb_init_one(slot) < 0) | ||
245 | break; | ||
246 | count++; | ||
247 | } | ||
248 | return (count > 0) ? 0 : -ENXIO; | ||
249 | } | 263 | } |
250 | 264 | ||
251 | static void __exit pmagbafb_exit(void) | 265 | static void __exit pmagbafb_exit(void) |
252 | { | 266 | { |
253 | while (root_pmagbafb_dev) | 267 | tc_unregister_driver(&pmagbafb_driver); |
254 | pmagbafb_exit_one(); | ||
255 | } | 268 | } |
256 | 269 | ||
257 | 270 | ||