aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/pmag-ba-fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/pmag-ba-fb.c')
-rw-r--r--drivers/video/pmag-ba-fb.c95
1 files changed, 54 insertions, 41 deletions
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
41struct pmagbafb_par { 41struct 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
49static struct fb_info *root_pmagbafb_dev;
50
51static struct fb_var_screeninfo pmagbafb_defined __initdata = { 47static 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
148static int __init pmagbafb_init_one(int slot) 144static 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:
204err_mmio_map: 203err_mmio_map:
205 iounmap(par->mmio); 204 iounmap(par->mmio);
206 205
206err_resource:
207 release_mem_region(start, len);
208
207err_cmap: 209err_cmap:
208 fb_dealloc_cmap(&info->cmap); 210 fb_dealloc_cmap(&info->cmap);
209 211
210err_alloc: 212err_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
217static void __exit pmagbafb_exit_one(void) 217static 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 */
240static const struct tc_device_id pmagbafb_tc_table[] = {
241 { "DEC ", "PMAG-BA " },
242 { }
243};
244MODULE_DEVICE_TABLE(tc, pmagbafb_tc_table);
245
246static 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
235static int __init pmagbafb_init(void) 256static 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
251static void __exit pmagbafb_exit(void) 265static 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