aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2006-06-29 17:35:52 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-29 19:37:18 -0400
commit50312ce9dd794eef3df9e64194ba95ca730d82c8 (patch)
tree15703fd98b8b757197d43e11f8de791bbc3b8f00
parent3ca9fab410fbef6fc3a13284f5c26faccade21d1 (diff)
[SPARC]: Convert all FB SBUS drivers to of_driver framework.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/video/bw2.c213
-rw-r--r--drivers/video/cg14.c326
-rw-r--r--drivers/video/cg3.c217
-rw-r--r--drivers/video/cg6.c337
-rw-r--r--drivers/video/ffb.c466
-rw-r--r--drivers/video/leo.c294
-rw-r--r--drivers/video/p9100.c251
-rw-r--r--drivers/video/tcx.c224
8 files changed, 1179 insertions, 1149 deletions
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 6577fdfdfc16..c66e3d52cbf3 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -1,6 +1,6 @@
1/* bw2.c: BWTWO frame buffer driver 1/* bw2.c: BWTWO frame buffer driver
2 * 2 *
3 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 3 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) 4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
5 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) 5 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
6 * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) 6 * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -19,14 +19,11 @@
19#include <linux/mm.h> 19#include <linux/mm.h>
20 20
21#include <asm/io.h> 21#include <asm/io.h>
22#include <asm/sbus.h>
23#include <asm/oplib.h> 22#include <asm/oplib.h>
23#include <asm/prom.h>
24#include <asm/of_device.h>
24#include <asm/fbio.h> 25#include <asm/fbio.h>
25 26
26#ifdef CONFIG_SPARC32
27#include <asm/sun4paddr.h>
28#endif
29
30#include "sbuslib.h" 27#include "sbuslib.h"
31 28
32/* 29/*
@@ -59,30 +56,30 @@ static struct fb_ops bw2_ops = {
59#define BWTWO_REGISTER_OFFSET 0x400000 56#define BWTWO_REGISTER_OFFSET 0x400000
60 57
61struct bt_regs { 58struct bt_regs {
62 volatile u32 addr; 59 u32 addr;
63 volatile u32 color_map; 60 u32 color_map;
64 volatile u32 control; 61 u32 control;
65 volatile u32 cursor; 62 u32 cursor;
66}; 63};
67 64
68struct bw2_regs { 65struct bw2_regs {
69 struct bt_regs cmap; 66 struct bt_regs cmap;
70 volatile u8 control; 67 u8 control;
71 volatile u8 status; 68 u8 status;
72 volatile u8 cursor_start; 69 u8 cursor_start;
73 volatile u8 cursor_end; 70 u8 cursor_end;
74 volatile u8 h_blank_start; 71 u8 h_blank_start;
75 volatile u8 h_blank_end; 72 u8 h_blank_end;
76 volatile u8 h_sync_start; 73 u8 h_sync_start;
77 volatile u8 h_sync_end; 74 u8 h_sync_end;
78 volatile u8 comp_sync_end; 75 u8 comp_sync_end;
79 volatile u8 v_blank_start_high; 76 u8 v_blank_start_high;
80 volatile u8 v_blank_start_low; 77 u8 v_blank_start_low;
81 volatile u8 v_blank_end; 78 u8 v_blank_end;
82 volatile u8 v_sync_start; 79 u8 v_sync_start;
83 volatile u8 v_sync_end; 80 u8 v_sync_end;
84 volatile u8 xfer_holdoff_start; 81 u8 xfer_holdoff_start;
85 volatile u8 xfer_holdoff_end; 82 u8 xfer_holdoff_end;
86}; 83};
87 84
88/* Status Register Constants */ 85/* Status Register Constants */
@@ -117,9 +114,8 @@ struct bw2_par {
117#define BW2_FLAG_BLANKED 0x00000001 114#define BW2_FLAG_BLANKED 0x00000001
118 115
119 unsigned long physbase; 116 unsigned long physbase;
117 unsigned long which_io;
120 unsigned long fbsize; 118 unsigned long fbsize;
121
122 struct sbus_dev *sdev;
123}; 119};
124 120
125/** 121/**
@@ -174,9 +170,7 @@ static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma)
174 170
175 return sbusfb_mmap_helper(bw2_mmap_map, 171 return sbusfb_mmap_helper(bw2_mmap_map,
176 par->physbase, par->fbsize, 172 par->physbase, par->fbsize,
177 (par->sdev ? 173 par->which_io,
178 par->sdev->reg_addrs[0].which_io :
179 0),
180 vma); 174 vma);
181} 175}
182 176
@@ -288,139 +282,124 @@ static void bw2_do_default_mode(struct bw2_par *par, struct fb_info *info,
288struct all_info { 282struct all_info {
289 struct fb_info info; 283 struct fb_info info;
290 struct bw2_par par; 284 struct bw2_par par;
291 struct list_head list;
292}; 285};
293static LIST_HEAD(bw2_list);
294 286
295static void bw2_init_one(struct sbus_dev *sdev) 287static int __devinit bw2_init_one(struct of_device *op)
296{ 288{
289 struct device_node *dp = op->node;
297 struct all_info *all; 290 struct all_info *all;
298 struct resource *resp; 291 int linebytes, err;
299#ifdef CONFIG_SUN4
300 struct resource res;
301#endif
302 int linebytes;
303 292
304 all = kmalloc(sizeof(*all), GFP_KERNEL); 293 all = kzalloc(sizeof(*all), GFP_KERNEL);
305 if (!all) { 294 if (!all)
306 printk(KERN_ERR "bw2: Cannot allocate memory.\n"); 295 return -ENOMEM;
307 return;
308 }
309 memset(all, 0, sizeof(*all));
310
311 INIT_LIST_HEAD(&all->list);
312 296
313 spin_lock_init(&all->par.lock); 297 spin_lock_init(&all->par.lock);
314 all->par.sdev = sdev; 298
315 299 all->par.physbase = op->resource[0].start;
316#ifdef CONFIG_SUN4 300 all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
317 if (!sdev) { 301
318 all->par.physbase = sun4_bwtwo_physaddr; 302 sbusfb_fill_var(&all->info.var, dp->node, 1);
319 res.start = sun4_bwtwo_physaddr; 303 linebytes = of_getintprop_default(dp, "linebytes",
320 res.end = res.start + BWTWO_REGISTER_OFFSET + sizeof(struct bw2_regs) - 1; 304 all->info.var.xres);
321 res.flags = IORESOURCE_IO; 305
322 resp = &res;
323 all->info.var.xres = all->info.var.xres_virtual = 1152;
324 all->info.var.yres = all->info.var.yres_virtual = 900;
325 all->info.var.bits_per_pixel = 1;
326 linebytes = 1152 / 8;
327 } else
328#else
329 {
330 BUG_ON(!sdev);
331 all->par.physbase = sdev->reg_addrs[0].phys_addr;
332 resp = &sdev->resource[0];
333 sbusfb_fill_var(&all->info.var, (sdev ? sdev->prom_node : 0), 1);
334 linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
335 all->info.var.xres);
336 }
337#endif
338 all->info.var.red.length = all->info.var.green.length = 306 all->info.var.red.length = all->info.var.green.length =
339 all->info.var.blue.length = all->info.var.bits_per_pixel; 307 all->info.var.blue.length = all->info.var.bits_per_pixel;
340 all->info.var.red.offset = all->info.var.green.offset = 308 all->info.var.red.offset = all->info.var.green.offset =
341 all->info.var.blue.offset = 0; 309 all->info.var.blue.offset = 0;
342 310
343 all->par.regs = sbus_ioremap(resp, BWTWO_REGISTER_OFFSET, 311 all->par.regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET,
344 sizeof(struct bw2_regs), "bw2 regs"); 312 sizeof(struct bw2_regs), "bw2 regs");
345 313
346 if (sdev && !prom_getbool(sdev->prom_node, "width")) 314 if (!of_find_property(dp, "width", NULL))
347 bw2_do_default_mode(&all->par, &all->info, &linebytes); 315 bw2_do_default_mode(&all->par, &all->info, &linebytes);
348 316
349 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); 317 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
350 318
351 all->info.flags = FBINFO_DEFAULT; 319 all->info.flags = FBINFO_DEFAULT;
352 all->info.fbops = &bw2_ops; 320 all->info.fbops = &bw2_ops;
353#if defined(CONFIG_SPARC32) 321
354 if (sdev) 322 all->info.screen_base =
355 all->info.screen_base = (char __iomem *) 323 sbus_ioremap(&op->resource[0], 0, all->par.fbsize, "bw2 ram");
356 prom_getintdefault(sdev->prom_node, "address", 0);
357#endif
358 if (!all->info.screen_base)
359 all->info.screen_base =
360 sbus_ioremap(resp, 0, all->par.fbsize, "bw2 ram");
361 all->info.par = &all->par; 324 all->info.par = &all->par;
362 325
363 bw2_blank(0, &all->info); 326 bw2_blank(0, &all->info);
364 327
365 bw2_init_fix(&all->info, linebytes); 328 bw2_init_fix(&all->info, linebytes);
366 329
367 if (register_framebuffer(&all->info) < 0) { 330 err= register_framebuffer(&all->info);
368 printk(KERN_ERR "bw2: Could not register framebuffer.\n"); 331 if (err < 0) {
332 of_iounmap(all->par.regs, sizeof(struct bw2_regs));
333 of_iounmap(all->info.screen_base, all->par.fbsize);
369 kfree(all); 334 kfree(all);
370 return; 335 return err;
371 } 336 }
372 337
373 list_add(&all->list, &bw2_list); 338 dev_set_drvdata(&op->dev, all);
339
340 printk("%s: bwtwo at %lx:%lx\n",
341 dp->full_name,
342 all->par.which_io, all->par.physbase);
374 343
375 printk("bw2: bwtwo at %lx:%lx\n", 344 return 0;
376 (long) (sdev ? sdev->reg_addrs[0].which_io : 0),
377 (long) all->par.physbase);
378} 345}
379 346
380int __init bw2_init(void) 347static int __devinit bw2_probe(struct of_device *dev, const struct of_device_id *match)
381{ 348{
382 struct sbus_bus *sbus; 349 struct of_device *op = to_of_device(&dev->dev);
383 struct sbus_dev *sdev;
384 350
385 if (fb_get_options("bw2fb", NULL)) 351 return bw2_init_one(op);
386 return -ENODEV; 352}
387 353
388#ifdef CONFIG_SUN4 354static int __devexit bw2_remove(struct of_device *dev)
389 bw2_init_one(NULL); 355{
390#endif 356 struct all_info *all = dev_get_drvdata(&dev->dev);
391 for_all_sbusdev(sdev, sbus) { 357
392 if (!strcmp(sdev->prom_name, "bwtwo")) 358 unregister_framebuffer(&all->info);
393 bw2_init_one(sdev); 359
394 } 360 of_iounmap(all->par.regs, sizeof(struct bw2_regs));
361 of_iounmap(all->info.screen_base, all->par.fbsize);
362
363 kfree(all);
364
365 dev_set_drvdata(&dev->dev, NULL);
395 366
396 return 0; 367 return 0;
397} 368}
398 369
399void __exit bw2_exit(void) 370static struct of_device_id bw2_match[] = {
400{ 371 {
401 struct list_head *pos, *tmp; 372 .name = "bwtwo",
373 },
374 {},
375};
376MODULE_DEVICE_TABLE(of, bw2_match);
402 377
403 list_for_each_safe(pos, tmp, &bw2_list) { 378static struct of_platform_driver bw2_driver = {
404 struct all_info *all = list_entry(pos, typeof(*all), list); 379 .name = "bw2",
380 .match_table = bw2_match,
381 .probe = bw2_probe,
382 .remove = __devexit_p(bw2_remove),
383};
405 384
406 unregister_framebuffer(&all->info); 385static int __init bw2_init(void)
407 kfree(all); 386{
408 } 387 if (fb_get_options("bw2fb", NULL))
388 return -ENODEV;
389
390 return of_register_driver(&bw2_driver, &of_bus_type);
409} 391}
410 392
411int __init 393static void __exit bw2_exit(void)
412bw2_setup(char *arg)
413{ 394{
414 /* No cmdline options yet... */ 395 return of_unregister_driver(&bw2_driver);
415 return 0;
416} 396}
417 397
418module_init(bw2_init);
419 398
420#ifdef MODULE 399module_init(bw2_init);
421module_exit(bw2_exit); 400module_exit(bw2_exit);
422#endif
423 401
424MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets"); 402MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets");
425MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); 403MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
404MODULE_VERSION("2.0");
426MODULE_LICENSE("GPL"); 405MODULE_LICENSE("GPL");
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index 63b6c79c8a0a..7f926c619b61 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -1,6 +1,6 @@
1/* cg14.c: CGFOURTEEN frame buffer driver 1/* cg14.c: CGFOURTEEN frame buffer driver
2 * 2 *
3 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 3 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) 4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
5 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) 5 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
6 * 6 *
@@ -18,8 +18,8 @@
18#include <linux/mm.h> 18#include <linux/mm.h>
19 19
20#include <asm/io.h> 20#include <asm/io.h>
21#include <asm/sbus.h> 21#include <asm/prom.h>
22#include <asm/oplib.h> 22#include <asm/of_device.h>
23#include <asm/fbio.h> 23#include <asm/fbio.h>
24 24
25#include "sbuslib.h" 25#include "sbuslib.h"
@@ -99,73 +99,73 @@ static struct fb_ops cg14_ops = {
99#define CG14_MCR_PIXMODE_32 3 99#define CG14_MCR_PIXMODE_32 3
100 100
101struct cg14_regs{ 101struct cg14_regs{
102 volatile u8 mcr; /* Master Control Reg */ 102 u8 mcr; /* Master Control Reg */
103 volatile u8 ppr; /* Packed Pixel Reg */ 103 u8 ppr; /* Packed Pixel Reg */
104 volatile u8 tms[2]; /* Test Mode Status Regs */ 104 u8 tms[2]; /* Test Mode Status Regs */
105 volatile u8 msr; /* Master Status Reg */ 105 u8 msr; /* Master Status Reg */
106 volatile u8 fsr; /* Fault Status Reg */ 106 u8 fsr; /* Fault Status Reg */
107 volatile u8 rev; /* Revision & Impl */ 107 u8 rev; /* Revision & Impl */
108 volatile u8 ccr; /* Clock Control Reg */ 108 u8 ccr; /* Clock Control Reg */
109 volatile u32 tmr; /* Test Mode Read Back */ 109 u32 tmr; /* Test Mode Read Back */
110 volatile u8 mod; /* Monitor Operation Data Reg */ 110 u8 mod; /* Monitor Operation Data Reg */
111 volatile u8 acr; /* Aux Control */ 111 u8 acr; /* Aux Control */
112 u8 xxx0[6]; 112 u8 xxx0[6];
113 volatile u16 hct; /* Hor Counter */ 113 u16 hct; /* Hor Counter */
114 volatile u16 vct; /* Vert Counter */ 114 u16 vct; /* Vert Counter */
115 volatile u16 hbs; /* Hor Blank Start */ 115 u16 hbs; /* Hor Blank Start */
116 volatile u16 hbc; /* Hor Blank Clear */ 116 u16 hbc; /* Hor Blank Clear */
117 volatile u16 hss; /* Hor Sync Start */ 117 u16 hss; /* Hor Sync Start */
118 volatile u16 hsc; /* Hor Sync Clear */ 118 u16 hsc; /* Hor Sync Clear */
119 volatile u16 csc; /* Composite Sync Clear */ 119 u16 csc; /* Composite Sync Clear */
120 volatile u16 vbs; /* Vert Blank Start */ 120 u16 vbs; /* Vert Blank Start */
121 volatile u16 vbc; /* Vert Blank Clear */ 121 u16 vbc; /* Vert Blank Clear */
122 volatile u16 vss; /* Vert Sync Start */ 122 u16 vss; /* Vert Sync Start */
123 volatile u16 vsc; /* Vert Sync Clear */ 123 u16 vsc; /* Vert Sync Clear */
124 volatile u16 xcs; 124 u16 xcs;
125 volatile u16 xcc; 125 u16 xcc;
126 volatile u16 fsa; /* Fault Status Address */ 126 u16 fsa; /* Fault Status Address */
127 volatile u16 adr; /* Address Registers */ 127 u16 adr; /* Address Registers */
128 u8 xxx1[0xce]; 128 u8 xxx1[0xce];
129 volatile u8 pcg[0x100]; /* Pixel Clock Generator */ 129 u8 pcg[0x100]; /* Pixel Clock Generator */
130 volatile u32 vbr; /* Frame Base Row */ 130 u32 vbr; /* Frame Base Row */
131 volatile u32 vmcr; /* VBC Master Control */ 131 u32 vmcr; /* VBC Master Control */
132 volatile u32 vcr; /* VBC refresh */ 132 u32 vcr; /* VBC refresh */
133 volatile u32 vca; /* VBC Config */ 133 u32 vca; /* VBC Config */
134}; 134};
135 135
136#define CG14_CCR_ENABLE 0x04 136#define CG14_CCR_ENABLE 0x04
137#define CG14_CCR_SELECT 0x02 /* HW/Full screen */ 137#define CG14_CCR_SELECT 0x02 /* HW/Full screen */
138 138
139struct cg14_cursor { 139struct cg14_cursor {
140 volatile u32 cpl0[32]; /* Enable plane 0 */ 140 u32 cpl0[32]; /* Enable plane 0 */
141 volatile u32 cpl1[32]; /* Color selection plane */ 141 u32 cpl1[32]; /* Color selection plane */
142 volatile u8 ccr; /* Cursor Control Reg */ 142 u8 ccr; /* Cursor Control Reg */
143 u8 xxx0[3]; 143 u8 xxx0[3];
144 volatile u16 cursx; /* Cursor x,y position */ 144 u16 cursx; /* Cursor x,y position */
145 volatile u16 cursy; /* Cursor x,y position */ 145 u16 cursy; /* Cursor x,y position */
146 volatile u32 color0; 146 u32 color0;
147 volatile u32 color1; 147 u32 color1;
148 u32 xxx1[0x1bc]; 148 u32 xxx1[0x1bc];
149 volatile u32 cpl0i[32]; /* Enable plane 0 autoinc */ 149 u32 cpl0i[32]; /* Enable plane 0 autoinc */
150 volatile u32 cpl1i[32]; /* Color selection autoinc */ 150 u32 cpl1i[32]; /* Color selection autoinc */
151}; 151};
152 152
153struct cg14_dac { 153struct cg14_dac {
154 volatile u8 addr; /* Address Register */ 154 u8 addr; /* Address Register */
155 u8 xxx0[255]; 155 u8 xxx0[255];
156 volatile u8 glut; /* Gamma table */ 156 u8 glut; /* Gamma table */
157 u8 xxx1[255]; 157 u8 xxx1[255];
158 volatile u8 select; /* Register Select */ 158 u8 select; /* Register Select */
159 u8 xxx2[255]; 159 u8 xxx2[255];
160 volatile u8 mode; /* Mode Register */ 160 u8 mode; /* Mode Register */
161}; 161};
162 162
163struct cg14_xlut{ 163struct cg14_xlut{
164 volatile u8 x_xlut [256]; 164 u8 x_xlut [256];
165 volatile u8 x_xlutd [256]; 165 u8 x_xlutd [256];
166 u8 xxx0[0x600]; 166 u8 xxx0[0x600];
167 volatile u8 x_xlut_inc [256]; 167 u8 x_xlut_inc [256];
168 volatile u8 x_xlutd_inc [256]; 168 u8 x_xlutd_inc [256];
169}; 169};
170 170
171/* Color look up table (clut) */ 171/* Color look up table (clut) */
@@ -204,7 +204,6 @@ struct cg14_par {
204 204
205 int mode; 205 int mode;
206 int ramsize; 206 int ramsize;
207 struct sbus_dev *sdev;
208}; 207};
209 208
210static void __cg14_reset(struct cg14_par *par) 209static void __cg14_reset(struct cg14_par *par)
@@ -355,14 +354,9 @@ static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
355 * Initialisation 354 * Initialisation
356 */ 355 */
357 356
358static void cg14_init_fix(struct fb_info *info, int linebytes) 357static void cg14_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
359{ 358{
360 struct cg14_par *par = (struct cg14_par *)info->par; 359 const char *name = dp->name;
361 const char *name;
362
363 name = "cgfourteen";
364 if (par->sdev)
365 name = par->sdev->prom_name;
366 360
367 strlcpy(info->fix.id, name, sizeof(info->fix.id)); 361 strlcpy(info->fix.id, name, sizeof(info->fix.id));
368 362
@@ -456,98 +450,81 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __initdata = {
456struct all_info { 450struct all_info {
457 struct fb_info info; 451 struct fb_info info;
458 struct cg14_par par; 452 struct cg14_par par;
459 struct list_head list;
460}; 453};
461static LIST_HEAD(cg14_list);
462 454
463static void cg14_init_one(struct sbus_dev *sdev, int node, int parent_node) 455static void cg14_unmap_regs(struct all_info *all)
464{ 456{
465 struct all_info *all; 457 if (all->par.regs)
466 unsigned long phys, rphys; 458 of_iounmap(all->par.regs, sizeof(struct cg14_regs));
467 u32 bases[6]; 459 if (all->par.clut)
468 int is_8mb, linebytes, i; 460 of_iounmap(all->par.clut, sizeof(struct cg14_clut));
469 461 if (all->par.cursor)
470 if (!sdev) { 462 of_iounmap(all->par.cursor, sizeof(struct cg14_cursor));
471 if (prom_getproperty(node, "address", 463 if (all->info.screen_base)
472 (char *) &bases[0], sizeof(bases)) <= 0 464 of_iounmap(all->info.screen_base, all->par.fbsize);
473 || !bases[0]) { 465}
474 printk(KERN_ERR "cg14: Device is not mapped.\n");
475 return;
476 }
477 if (__get_iospace(bases[0]) != __get_iospace(bases[1])) {
478 printk(KERN_ERR "cg14: I/O spaces don't match.\n");
479 return;
480 }
481 }
482 466
483 all = kmalloc(sizeof(*all), GFP_KERNEL); 467static int __devinit cg14_init_one(struct of_device *op)
484 if (!all) { 468{
485 printk(KERN_ERR "cg14: Cannot allocate memory.\n"); 469 struct device_node *dp = op->node;
486 return; 470 struct all_info *all;
487 } 471 int is_8mb, linebytes, i, err;
488 memset(all, 0, sizeof(*all));
489 472
490 INIT_LIST_HEAD(&all->list); 473 all = kzalloc(sizeof(*all), GFP_KERNEL);
474 if (!all)
475 return -ENOMEM;
491 476
492 spin_lock_init(&all->par.lock); 477 spin_lock_init(&all->par.lock);
493 478
494 sbusfb_fill_var(&all->info.var, node, 8); 479 sbusfb_fill_var(&all->info.var, dp->node, 8);
495 all->info.var.red.length = 8; 480 all->info.var.red.length = 8;
496 all->info.var.green.length = 8; 481 all->info.var.green.length = 8;
497 all->info.var.blue.length = 8; 482 all->info.var.blue.length = 8;
498 483
499 linebytes = prom_getintdefault(node, "linebytes", 484 linebytes = of_getintprop_default(dp, "linebytes",
500 all->info.var.xres); 485 all->info.var.xres);
501 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); 486 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
502 487
503 all->par.sdev = sdev; 488 if (!strcmp(dp->parent->name, "sbus") ||
504 if (sdev) { 489 !strcmp(dp->parent->name, "sbi")) {
505 rphys = sdev->reg_addrs[0].phys_addr; 490 all->par.physbase = op->resource[0].start;
506 all->par.physbase = phys = sdev->reg_addrs[1].phys_addr; 491 all->par.iospace = op->resource[0].flags & IORESOURCE_BITS;
507 all->par.iospace = sdev->reg_addrs[0].which_io;
508
509 all->par.regs = sbus_ioremap(&sdev->resource[0], 0,
510 sizeof(struct cg14_regs),
511 "cg14 regs");
512 all->par.clut = sbus_ioremap(&sdev->resource[0], CG14_CLUT1,
513 sizeof(struct cg14_clut),
514 "cg14 clut");
515 all->par.cursor = sbus_ioremap(&sdev->resource[0], CG14_CURSORREGS,
516 sizeof(struct cg14_cursor),
517 "cg14 cursor");
518 all->info.screen_base = sbus_ioremap(&sdev->resource[1], 0,
519 all->par.fbsize, "cg14 ram");
520 } else { 492 } else {
521 rphys = __get_phys(bases[0]); 493 all->par.physbase = op->resource[1].start;
522 all->par.physbase = phys = __get_phys(bases[1]); 494 all->par.iospace = op->resource[0].flags & IORESOURCE_BITS;
523 all->par.iospace = __get_iospace(bases[0]);
524 all->par.regs = (struct cg14_regs __iomem *)(unsigned long)bases[0];
525 all->par.clut = (struct cg14_clut __iomem *)((unsigned long)bases[0] +
526 CG14_CLUT1);
527 all->par.cursor =
528 (struct cg14_cursor __iomem *)((unsigned long)bases[0] +
529 CG14_CURSORREGS);
530
531 all->info.screen_base = (char __iomem *)(unsigned long)bases[1];
532 } 495 }
533 496
534 prom_getproperty(node, "reg", (char *) &bases[0], sizeof(bases)); 497 all->par.regs = of_ioremap(&op->resource[0], 0,
535 is_8mb = (bases[5] == 0x800000); 498 sizeof(struct cg14_regs), "cg14 regs");
499 all->par.clut = of_ioremap(&op->resource[0], CG14_CLUT1,
500 sizeof(struct cg14_clut), "cg14 clut");
501 all->par.cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS,
502 sizeof(struct cg14_cursor), "cg14 cursor");
536 503
537 if (sizeof(all->par.mmap_map) != sizeof(__cg14_mmap_map)) { 504 all->info.screen_base = of_ioremap(&op->resource[1], 0,
538 extern void __cg14_mmap_sized_wrongly(void); 505 all->par.fbsize, "cg14 ram");
539 506
540 __cg14_mmap_sized_wrongly(); 507 if (!all->par.regs || !all->par.clut || !all->par.cursor ||
541 } 508 !all->info.screen_base)
509 cg14_unmap_regs(all);
510
511 is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) ==
512 (8 * 1024 * 1024));
513
514 BUILD_BUG_ON(sizeof(all->par.mmap_map) != sizeof(__cg14_mmap_map));
542 515
543 memcpy(&all->par.mmap_map, &__cg14_mmap_map, sizeof(all->par.mmap_map)); 516 memcpy(&all->par.mmap_map, &__cg14_mmap_map,
517 sizeof(all->par.mmap_map));
518
544 for (i = 0; i < CG14_MMAP_ENTRIES; i++) { 519 for (i = 0; i < CG14_MMAP_ENTRIES; i++) {
545 struct sbus_mmap_map *map = &all->par.mmap_map[i]; 520 struct sbus_mmap_map *map = &all->par.mmap_map[i];
546 521
547 if (!map->size) 522 if (!map->size)
548 break; 523 break;
549 if (map->poff & 0x80000000) 524 if (map->poff & 0x80000000)
550 map->poff = (map->poff & 0x7fffffff) + rphys - phys; 525 map->poff = (map->poff & 0x7fffffff) +
526 (op->resource[0].start -
527 op->resource[1].start);
551 if (is_8mb && 528 if (is_8mb &&
552 map->size >= 0x100000 && 529 map->size >= 0x100000 &&
553 map->size <= 0x400000) 530 map->size <= 0x400000)
@@ -564,84 +541,87 @@ static void cg14_init_one(struct sbus_dev *sdev, int node, int parent_node)
564 __cg14_reset(&all->par); 541 __cg14_reset(&all->par);
565 542
566 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { 543 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
567 printk(KERN_ERR "cg14: Could not allocate color map.\n"); 544 cg14_unmap_regs(all);
568 kfree(all); 545 kfree(all);
569 return; 546 return -ENOMEM;
570 } 547 }
571 fb_set_cmap(&all->info.cmap, &all->info); 548 fb_set_cmap(&all->info.cmap, &all->info);
572 549
573 cg14_init_fix(&all->info, linebytes); 550 cg14_init_fix(&all->info, linebytes, dp);
574 551
575 if (register_framebuffer(&all->info) < 0) { 552 err = register_framebuffer(&all->info);
576 printk(KERN_ERR "cg14: Could not register framebuffer.\n"); 553 if (err < 0) {
577 fb_dealloc_cmap(&all->info.cmap); 554 fb_dealloc_cmap(&all->info.cmap);
555 cg14_unmap_regs(all);
578 kfree(all); 556 kfree(all);
579 return; 557 return err;
580 } 558 }
581 559
582 list_add(&all->list, &cg14_list); 560 dev_set_drvdata(&op->dev, all);
583 561
584 printk("cg14: cgfourteen at %lx:%lx, %dMB\n", 562 printk("%s: cgfourteen at %lx:%lx, %dMB\n",
585 all->par.iospace, all->par.physbase, all->par.ramsize >> 20); 563 dp->full_name,
564 all->par.iospace, all->par.physbase,
565 all->par.ramsize >> 20);
586 566
567 return 0;
587} 568}
588 569
589int __init cg14_init(void) 570static int __devinit cg14_probe(struct of_device *dev, const struct of_device_id *match)
590{ 571{
591 struct sbus_bus *sbus; 572 struct of_device *op = to_of_device(&dev->dev);
592 struct sbus_dev *sdev;
593 573
594 if (fb_get_options("cg14fb", NULL)) 574 return cg14_init_one(op);
595 return -ENODEV; 575}
596 576
597#ifdef CONFIG_SPARC32 577static int __devexit cg14_remove(struct of_device *dev)
598 { 578{
599 int root, node; 579 struct all_info *all = dev_get_drvdata(&dev->dev);
600 580
601 root = prom_getchild(prom_root_node); 581 unregister_framebuffer(&all->info);
602 root = prom_searchsiblings(root, "obio"); 582 fb_dealloc_cmap(&all->info.cmap);
603 if (root) { 583
604 node = prom_searchsiblings(prom_getchild(root), 584 cg14_unmap_regs(all);
605 "cgfourteen"); 585
606 if (node) 586 kfree(all);
607 cg14_init_one(NULL, node, root); 587
608 } 588 dev_set_drvdata(&dev->dev, NULL);
609 }
610#endif
611 for_all_sbusdev(sdev, sbus) {
612 if (!strcmp(sdev->prom_name, "cgfourteen"))
613 cg14_init_one(sdev, sdev->prom_node, sbus->prom_node);
614 }
615 589
616 return 0; 590 return 0;
617} 591}
618 592
619void __exit cg14_exit(void) 593static struct of_device_id cg14_match[] = {
620{ 594 {
621 struct list_head *pos, *tmp; 595 .name = "cgfourteen",
596 },
597 {},
598};
599MODULE_DEVICE_TABLE(of, cg14_match);
622 600
623 list_for_each_safe(pos, tmp, &cg14_list) { 601static struct of_platform_driver cg14_driver = {
624 struct all_info *all = list_entry(pos, typeof(*all), list); 602 .name = "cg14",
603 .match_table = cg14_match,
604 .probe = cg14_probe,
605 .remove = __devexit_p(cg14_remove),
606};
625 607
626 unregister_framebuffer(&all->info); 608int __init cg14_init(void)
627 fb_dealloc_cmap(&all->info.cmap); 609{
628 kfree(all); 610 if (fb_get_options("cg14fb", NULL))
629 } 611 return -ENODEV;
612
613 return of_register_driver(&cg14_driver, &of_bus_type);
630} 614}
631 615
632int __init 616void __exit cg14_exit(void)
633cg14_setup(char *arg)
634{ 617{
635 /* No cmdline options yet... */ 618 of_unregister_driver(&cg14_driver);
636 return 0;
637} 619}
638 620
639module_init(cg14_init); 621module_init(cg14_init);
640
641#ifdef MODULE
642module_exit(cg14_exit); 622module_exit(cg14_exit);
643#endif
644 623
645MODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets"); 624MODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets");
646MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); 625MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
626MODULE_VERSION("2.0");
647MODULE_LICENSE("GPL"); 627MODULE_LICENSE("GPL");
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 3de6e1b5ab2f..9c8c753ef454 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -1,6 +1,6 @@
1/* cg3.c: CGTHREE frame buffer driver 1/* cg3.c: CGTHREE frame buffer driver
2 * 2 *
3 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 3 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) 4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
5 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) 5 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
6 * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) 6 * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -19,8 +19,9 @@
19#include <linux/mm.h> 19#include <linux/mm.h>
20 20
21#include <asm/io.h> 21#include <asm/io.h>
22#include <asm/sbus.h>
23#include <asm/oplib.h> 22#include <asm/oplib.h>
23#include <asm/prom.h>
24#include <asm/of_device.h>
24#include <asm/fbio.h> 25#include <asm/fbio.h>
25 26
26#include "sbuslib.h" 27#include "sbuslib.h"
@@ -80,30 +81,30 @@ enum cg3_type {
80}; 81};
81 82
82struct bt_regs { 83struct bt_regs {
83 volatile u32 addr; 84 u32 addr;
84 volatile u32 color_map; 85 u32 color_map;
85 volatile u32 control; 86 u32 control;
86 volatile u32 cursor; 87 u32 cursor;
87}; 88};
88 89
89struct cg3_regs { 90struct cg3_regs {
90 struct bt_regs cmap; 91 struct bt_regs cmap;
91 volatile u8 control; 92 u8 control;
92 volatile u8 status; 93 u8 status;
93 volatile u8 cursor_start; 94 u8 cursor_start;
94 volatile u8 cursor_end; 95 u8 cursor_end;
95 volatile u8 h_blank_start; 96 u8 h_blank_start;
96 volatile u8 h_blank_end; 97 u8 h_blank_end;
97 volatile u8 h_sync_start; 98 u8 h_sync_start;
98 volatile u8 h_sync_end; 99 u8 h_sync_end;
99 volatile u8 comp_sync_end; 100 u8 comp_sync_end;
100 volatile u8 v_blank_start_high; 101 u8 v_blank_start_high;
101 volatile u8 v_blank_start_low; 102 u8 v_blank_start_low;
102 volatile u8 v_blank_end; 103 u8 v_blank_end;
103 volatile u8 v_sync_start; 104 u8 v_sync_start;
104 volatile u8 v_sync_end; 105 u8 v_sync_end;
105 volatile u8 xfer_holdoff_start; 106 u8 xfer_holdoff_start;
106 volatile u8 xfer_holdoff_end; 107 u8 xfer_holdoff_end;
107}; 108};
108 109
109/* Offset of interesting structures in the OBIO space */ 110/* Offset of interesting structures in the OBIO space */
@@ -120,9 +121,8 @@ struct cg3_par {
120#define CG3_FLAG_RDI 0x00000002 121#define CG3_FLAG_RDI 0x00000002
121 122
122 unsigned long physbase; 123 unsigned long physbase;
124 unsigned long which_io;
123 unsigned long fbsize; 125 unsigned long fbsize;
124
125 struct sbus_dev *sdev;
126}; 126};
127 127
128/** 128/**
@@ -235,7 +235,7 @@ static int cg3_mmap(struct fb_info *info, struct vm_area_struct *vma)
235 235
236 return sbusfb_mmap_helper(cg3_mmap_map, 236 return sbusfb_mmap_helper(cg3_mmap_map,
237 par->physbase, par->fbsize, 237 par->physbase, par->fbsize,
238 par->sdev->reg_addrs[0].which_io, 238 par->which_io,
239 vma); 239 vma);
240} 240}
241 241
@@ -252,11 +252,9 @@ static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
252 */ 252 */
253 253
254static void 254static void
255cg3_init_fix(struct fb_info *info, int linebytes) 255cg3_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
256{ 256{
257 struct cg3_par *par = (struct cg3_par *)info->par; 257 strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
258
259 strlcpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id));
260 258
261 info->fix.type = FB_TYPE_PACKED_PIXELS; 259 info->fix.type = FB_TYPE_PACKED_PIXELS;
262 info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 260 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -267,16 +265,15 @@ cg3_init_fix(struct fb_info *info, int linebytes)
267} 265}
268 266
269static void cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var, 267static void cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var,
270 struct sbus_dev *sdev) 268 struct device_node *dp)
271{ 269{
272 char buffer[40]; 270 char *params;
273 char *p; 271 char *p;
274 int ww, hh; 272 int ww, hh;
275 273
276 *buffer = 0; 274 params = of_get_property(dp, "params", NULL);
277 prom_getstring(sdev->prom_node, "params", buffer, sizeof(buffer)); 275 if (params) {
278 if (*buffer) { 276 ww = simple_strtoul(params, &p, 10);
279 ww = simple_strtoul(buffer, &p, 10);
280 if (ww && *p == 'x') { 277 if (ww && *p == 'x') {
281 hh = simple_strtoul(p + 1, &p, 10); 278 hh = simple_strtoul(p + 1, &p, 10);
282 if (hh && *p == '-') { 279 if (hh && *p == '-') {
@@ -348,11 +345,11 @@ static void cg3_do_default_mode(struct cg3_par *par)
348 sbus_writeb(p[1], regp); 345 sbus_writeb(p[1], regp);
349 } 346 }
350 for (p = cg3_dacvals; *p; p += 2) { 347 for (p = cg3_dacvals; *p; p += 2) {
351 volatile u8 __iomem *regp; 348 u8 __iomem *regp;
352 349
353 regp = (volatile u8 __iomem *)&par->regs->cmap.addr; 350 regp = (u8 __iomem *)&par->regs->cmap.addr;
354 sbus_writeb(p[0], regp); 351 sbus_writeb(p[0], regp);
355 regp = (volatile u8 __iomem *)&par->regs->cmap.control; 352 regp = (u8 __iomem *)&par->regs->cmap.control;
356 sbus_writeb(p[1], regp); 353 sbus_writeb(p[1], regp);
357 } 354 }
358} 355}
@@ -360,129 +357,137 @@ static void cg3_do_default_mode(struct cg3_par *par)
360struct all_info { 357struct all_info {
361 struct fb_info info; 358 struct fb_info info;
362 struct cg3_par par; 359 struct cg3_par par;
363 struct list_head list;
364}; 360};
365static LIST_HEAD(cg3_list);
366 361
367static void cg3_init_one(struct sbus_dev *sdev) 362static int __devinit cg3_init_one(struct of_device *op)
368{ 363{
364 struct device_node *dp = op->node;
369 struct all_info *all; 365 struct all_info *all;
370 int linebytes; 366 int linebytes, err;
371
372 all = kmalloc(sizeof(*all), GFP_KERNEL);
373 if (!all) {
374 printk(KERN_ERR "cg3: Cannot allocate memory.\n");
375 return;
376 }
377 memset(all, 0, sizeof(*all));
378 367
379 INIT_LIST_HEAD(&all->list); 368 all = kzalloc(sizeof(*all), GFP_KERNEL);
369 if (!all)
370 return -ENOMEM;
380 371
381 spin_lock_init(&all->par.lock); 372 spin_lock_init(&all->par.lock);
382 all->par.sdev = sdev;
383 373
384 all->par.physbase = sdev->reg_addrs[0].phys_addr; 374 all->par.physbase = op->resource[0].start;
375 all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
385 376
386 sbusfb_fill_var(&all->info.var, sdev->prom_node, 8); 377 sbusfb_fill_var(&all->info.var, dp->node, 8);
387 all->info.var.red.length = 8; 378 all->info.var.red.length = 8;
388 all->info.var.green.length = 8; 379 all->info.var.green.length = 8;
389 all->info.var.blue.length = 8; 380 all->info.var.blue.length = 8;
390 if (!strcmp(sdev->prom_name, "cgRDI")) 381 if (!strcmp(dp->name, "cgRDI"))
391 all->par.flags |= CG3_FLAG_RDI; 382 all->par.flags |= CG3_FLAG_RDI;
392 if (all->par.flags & CG3_FLAG_RDI) 383 if (all->par.flags & CG3_FLAG_RDI)
393 cg3_rdi_maybe_fixup_var(&all->info.var, sdev); 384 cg3_rdi_maybe_fixup_var(&all->info.var, dp);
394 385
395 linebytes = prom_getintdefault(sdev->prom_node, "linebytes", 386 linebytes = of_getintprop_default(dp, "linebytes",
396 all->info.var.xres); 387 all->info.var.xres);
397 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); 388 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
398 389
399 all->par.regs = sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET, 390 all->par.regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET,
400 sizeof(struct cg3_regs), "cg3 regs"); 391 sizeof(struct cg3_regs), "cg3 regs");
401 392
402 all->info.flags = FBINFO_DEFAULT; 393 all->info.flags = FBINFO_DEFAULT;
403 all->info.fbops = &cg3_ops; 394 all->info.fbops = &cg3_ops;
404#ifdef CONFIG_SPARC32 395 all->info.screen_base =
405 all->info.screen_base = (char __iomem *) 396 of_ioremap(&op->resource[0], CG3_RAM_OFFSET,
406 prom_getintdefault(sdev->prom_node, "address", 0); 397 all->par.fbsize, "cg3 ram");
407#endif
408 if (!all->info.screen_base)
409 all->info.screen_base =
410 sbus_ioremap(&sdev->resource[0], CG3_RAM_OFFSET,
411 all->par.fbsize, "cg3 ram");
412 all->info.par = &all->par; 398 all->info.par = &all->par;
413 399
414 cg3_blank(0, &all->info); 400 cg3_blank(0, &all->info);
415 401
416 if (!prom_getbool(sdev->prom_node, "width")) 402 if (!of_find_property(dp, "width", NULL))
417 cg3_do_default_mode(&all->par); 403 cg3_do_default_mode(&all->par);
418 404
419 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { 405 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
420 printk(KERN_ERR "cg3: Could not allocate color map.\n"); 406 of_iounmap(all->par.regs, sizeof(struct cg3_regs));
407 of_iounmap(all->info.screen_base, all->par.fbsize);
421 kfree(all); 408 kfree(all);
422 return; 409 return -ENOMEM;
423 } 410 }
424 fb_set_cmap(&all->info.cmap, &all->info); 411 fb_set_cmap(&all->info.cmap, &all->info);
425 412
426 cg3_init_fix(&all->info, linebytes); 413 cg3_init_fix(&all->info, linebytes, dp);
427 414
428 if (register_framebuffer(&all->info) < 0) { 415 err = register_framebuffer(&all->info);
429 printk(KERN_ERR "cg3: Could not register framebuffer.\n"); 416 if (err < 0) {
430 fb_dealloc_cmap(&all->info.cmap); 417 fb_dealloc_cmap(&all->info.cmap);
418 of_iounmap(all->par.regs, sizeof(struct cg3_regs));
419 of_iounmap(all->info.screen_base, all->par.fbsize);
431 kfree(all); 420 kfree(all);
432 return; 421 return err;
433 } 422 }
434 423
435 list_add(&all->list, &cg3_list); 424 dev_set_drvdata(&op->dev, all);
425
426 printk("%s: cg3 at %lx:%lx\n",
427 dp->full_name, all->par.which_io, all->par.physbase);
436 428
437 printk("cg3: %s at %lx:%lx\n", 429 return 0;
438 sdev->prom_name,
439 (long) sdev->reg_addrs[0].which_io,
440 (long) sdev->reg_addrs[0].phys_addr);
441} 430}
442 431
443int __init cg3_init(void) 432static int __devinit cg3_probe(struct of_device *dev, const struct of_device_id *match)
444{ 433{
445 struct sbus_bus *sbus; 434 struct of_device *op = to_of_device(&dev->dev);
446 struct sbus_dev *sdev;
447 435
448 if (fb_get_options("cg3fb", NULL)) 436 return cg3_init_one(op);
449 return -ENODEV; 437}
450 438
451 for_all_sbusdev(sdev, sbus) { 439static int __devexit cg3_remove(struct of_device *dev)
452 if (!strcmp(sdev->prom_name, "cgthree") || 440{
453 !strcmp(sdev->prom_name, "cgRDI")) 441 struct all_info *all = dev_get_drvdata(&dev->dev);
454 cg3_init_one(sdev); 442
455 } 443 unregister_framebuffer(&all->info);
444 fb_dealloc_cmap(&all->info.cmap);
445
446 of_iounmap(all->par.regs, sizeof(struct cg3_regs));
447 of_iounmap(all->info.screen_base, all->par.fbsize);
448
449 kfree(all);
450
451 dev_set_drvdata(&dev->dev, NULL);
456 452
457 return 0; 453 return 0;
458} 454}
459 455
460void __exit cg3_exit(void) 456static struct of_device_id cg3_match[] = {
461{ 457 {
462 struct list_head *pos, *tmp; 458 .name = "cgthree",
459 },
460 {
461 .name = "cgRDI",
462 },
463 {},
464};
465MODULE_DEVICE_TABLE(of, cg3_match);
463 466
464 list_for_each_safe(pos, tmp, &cg3_list) { 467static struct of_platform_driver cg3_driver = {
465 struct all_info *all = list_entry(pos, typeof(*all), list); 468 .name = "cg3",
469 .match_table = cg3_match,
470 .probe = cg3_probe,
471 .remove = __devexit_p(cg3_remove),
472};
466 473
467 unregister_framebuffer(&all->info); 474static int __init cg3_init(void)
468 fb_dealloc_cmap(&all->info.cmap); 475{
469 kfree(all); 476 if (fb_get_options("cg3fb", NULL))
470 } 477 return -ENODEV;
478
479 return of_register_driver(&cg3_driver, &of_bus_type);
471} 480}
472 481
473int __init 482static void __exit cg3_exit(void)
474cg3_setup(char *arg)
475{ 483{
476 /* No cmdline options yet... */ 484 of_unregister_driver(&cg3_driver);
477 return 0;
478} 485}
479 486
480module_init(cg3_init); 487module_init(cg3_init);
481
482#ifdef MODULE
483module_exit(cg3_exit); 488module_exit(cg3_exit);
484#endif
485 489
486MODULE_DESCRIPTION("framebuffer driver for CGthree chipsets"); 490MODULE_DESCRIPTION("framebuffer driver for CGthree chipsets");
487MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); 491MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
492MODULE_VERSION("2.0");
488MODULE_LICENSE("GPL"); 493MODULE_LICENSE("GPL");
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 7aab91ead681..64146be2eeb0 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -1,6 +1,6 @@
1/* cg6.c: CGSIX (GX, GXplus, TGX) frame buffer driver 1/* cg6.c: CGSIX (GX, GXplus, TGX) frame buffer driver
2 * 2 *
3 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 3 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) 4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
5 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) 5 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
6 * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) 6 * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
@@ -19,8 +19,8 @@
19#include <linux/mm.h> 19#include <linux/mm.h>
20 20
21#include <asm/io.h> 21#include <asm/io.h>
22#include <asm/sbus.h> 22#include <asm/prom.h>
23#include <asm/oplib.h> 23#include <asm/of_device.h>
24#include <asm/fbio.h> 24#include <asm/fbio.h>
25 25
26#include "sbuslib.h" 26#include "sbuslib.h"
@@ -164,89 +164,89 @@ static struct fb_ops cg6_ops = {
164 164
165/* The contents are unknown */ 165/* The contents are unknown */
166struct cg6_tec { 166struct cg6_tec {
167 volatile int tec_matrix; 167 int tec_matrix;
168 volatile int tec_clip; 168 int tec_clip;
169 volatile int tec_vdc; 169 int tec_vdc;
170}; 170};
171 171
172struct cg6_thc { 172struct cg6_thc {
173 uint thc_pad0[512]; 173 u32 thc_pad0[512];
174 volatile uint thc_hs; /* hsync timing */ 174 u32 thc_hs; /* hsync timing */
175 volatile uint thc_hsdvs; 175 u32 thc_hsdvs;
176 volatile uint thc_hd; 176 u32 thc_hd;
177 volatile uint thc_vs; /* vsync timing */ 177 u32 thc_vs; /* vsync timing */
178 volatile uint thc_vd; 178 u32 thc_vd;
179 volatile uint thc_refresh; 179 u32 thc_refresh;
180 volatile uint thc_misc; 180 u32 thc_misc;
181 uint thc_pad1[56]; 181 u32 thc_pad1[56];
182 volatile uint thc_cursxy; /* cursor x,y position (16 bits each) */ 182 u32 thc_cursxy; /* cursor x,y position (16 bits each) */
183 volatile uint thc_cursmask[32]; /* cursor mask bits */ 183 u32 thc_cursmask[32]; /* cursor mask bits */
184 volatile uint thc_cursbits[32]; /* what to show where mask enabled */ 184 u32 thc_cursbits[32]; /* what to show where mask enabled */
185}; 185};
186 186
187struct cg6_fbc { 187struct cg6_fbc {
188 u32 xxx0[1]; 188 u32 xxx0[1];
189 volatile u32 mode; 189 u32 mode;
190 volatile u32 clip; 190 u32 clip;
191 u32 xxx1[1]; 191 u32 xxx1[1];
192 volatile u32 s; 192 u32 s;
193 volatile u32 draw; 193 u32 draw;
194 volatile u32 blit; 194 u32 blit;
195 volatile u32 font; 195 u32 font;
196 u32 xxx2[24]; 196 u32 xxx2[24];
197 volatile u32 x0, y0, z0, color0; 197 u32 x0, y0, z0, color0;
198 volatile u32 x1, y1, z1, color1; 198 u32 x1, y1, z1, color1;
199 volatile u32 x2, y2, z2, color2; 199 u32 x2, y2, z2, color2;
200 volatile u32 x3, y3, z3, color3; 200 u32 x3, y3, z3, color3;
201 volatile u32 offx, offy; 201 u32 offx, offy;
202 u32 xxx3[2]; 202 u32 xxx3[2];
203 volatile u32 incx, incy; 203 u32 incx, incy;
204 u32 xxx4[2]; 204 u32 xxx4[2];
205 volatile u32 clipminx, clipminy; 205 u32 clipminx, clipminy;
206 u32 xxx5[2]; 206 u32 xxx5[2];
207 volatile u32 clipmaxx, clipmaxy; 207 u32 clipmaxx, clipmaxy;
208 u32 xxx6[2]; 208 u32 xxx6[2];
209 volatile u32 fg; 209 u32 fg;
210 volatile u32 bg; 210 u32 bg;
211 volatile u32 alu; 211 u32 alu;
212 volatile u32 pm; 212 u32 pm;
213 volatile u32 pixelm; 213 u32 pixelm;
214 u32 xxx7[2]; 214 u32 xxx7[2];
215 volatile u32 patalign; 215 u32 patalign;
216 volatile u32 pattern[8]; 216 u32 pattern[8];
217 u32 xxx8[432]; 217 u32 xxx8[432];
218 volatile u32 apointx, apointy, apointz; 218 u32 apointx, apointy, apointz;
219 u32 xxx9[1]; 219 u32 xxx9[1];
220 volatile u32 rpointx, rpointy, rpointz; 220 u32 rpointx, rpointy, rpointz;
221 u32 xxx10[5]; 221 u32 xxx10[5];
222 volatile u32 pointr, pointg, pointb, pointa; 222 u32 pointr, pointg, pointb, pointa;
223 volatile u32 alinex, aliney, alinez; 223 u32 alinex, aliney, alinez;
224 u32 xxx11[1]; 224 u32 xxx11[1];
225 volatile u32 rlinex, rliney, rlinez; 225 u32 rlinex, rliney, rlinez;
226 u32 xxx12[5]; 226 u32 xxx12[5];
227 volatile u32 liner, lineg, lineb, linea; 227 u32 liner, lineg, lineb, linea;
228 volatile u32 atrix, atriy, atriz; 228 u32 atrix, atriy, atriz;
229 u32 xxx13[1]; 229 u32 xxx13[1];
230 volatile u32 rtrix, rtriy, rtriz; 230 u32 rtrix, rtriy, rtriz;
231 u32 xxx14[5]; 231 u32 xxx14[5];
232 volatile u32 trir, trig, trib, tria; 232 u32 trir, trig, trib, tria;
233 volatile u32 aquadx, aquady, aquadz; 233 u32 aquadx, aquady, aquadz;
234 u32 xxx15[1]; 234 u32 xxx15[1];
235 volatile u32 rquadx, rquady, rquadz; 235 u32 rquadx, rquady, rquadz;
236 u32 xxx16[5]; 236 u32 xxx16[5];
237 volatile u32 quadr, quadg, quadb, quada; 237 u32 quadr, quadg, quadb, quada;
238 volatile u32 arectx, arecty, arectz; 238 u32 arectx, arecty, arectz;
239 u32 xxx17[1]; 239 u32 xxx17[1];
240 volatile u32 rrectx, rrecty, rrectz; 240 u32 rrectx, rrecty, rrectz;
241 u32 xxx18[5]; 241 u32 xxx18[5];
242 volatile u32 rectr, rectg, rectb, recta; 242 u32 rectr, rectg, rectb, recta;
243}; 243};
244 244
245struct bt_regs { 245struct bt_regs {
246 volatile u32 addr; 246 u32 addr;
247 volatile u32 color_map; 247 u32 color_map;
248 volatile u32 control; 248 u32 control;
249 volatile u32 cursor; 249 u32 cursor;
250}; 250};
251 251
252struct cg6_par { 252struct cg6_par {
@@ -255,15 +255,14 @@ struct cg6_par {
255 struct cg6_fbc __iomem *fbc; 255 struct cg6_fbc __iomem *fbc;
256 struct cg6_thc __iomem *thc; 256 struct cg6_thc __iomem *thc;
257 struct cg6_tec __iomem *tec; 257 struct cg6_tec __iomem *tec;
258 volatile u32 __iomem *fhc; 258 u32 __iomem *fhc;
259 259
260 u32 flags; 260 u32 flags;
261#define CG6_FLAG_BLANKED 0x00000001 261#define CG6_FLAG_BLANKED 0x00000001
262 262
263 unsigned long physbase; 263 unsigned long physbase;
264 unsigned long which_io;
264 unsigned long fbsize; 265 unsigned long fbsize;
265
266 struct sbus_dev *sdev;
267}; 266};
268 267
269static int cg6_sync(struct fb_info *info) 268static int cg6_sync(struct fb_info *info)
@@ -529,8 +528,7 @@ static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma)
529 528
530 return sbusfb_mmap_helper(cg6_mmap_map, 529 return sbusfb_mmap_helper(cg6_mmap_map,
531 par->physbase, par->fbsize, 530 par->physbase, par->fbsize,
532 par->sdev->reg_addrs[0].which_io, 531 par->which_io, vma);
533 vma);
534} 532}
535 533
536static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) 534static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
@@ -658,62 +656,75 @@ static void cg6_chip_init(struct fb_info *info)
658struct all_info { 656struct all_info {
659 struct fb_info info; 657 struct fb_info info;
660 struct cg6_par par; 658 struct cg6_par par;
661 struct list_head list;
662}; 659};
663static LIST_HEAD(cg6_list);
664 660
665static void cg6_init_one(struct sbus_dev *sdev) 661static void cg6_unmap_regs(struct all_info *all)
666{ 662{
667 struct all_info *all; 663 if (all->par.fbc)
668 int linebytes; 664 of_iounmap(all->par.fbc, 4096);
665 if (all->par.tec)
666 of_iounmap(all->par.tec, sizeof(struct cg6_tec));
667 if (all->par.thc)
668 of_iounmap(all->par.thc, sizeof(struct cg6_thc));
669 if (all->par.bt)
670 of_iounmap(all->par.bt, sizeof(struct bt_regs));
671 if (all->par.fhc)
672 of_iounmap(all->par.fhc, sizeof(u32));
673
674 if (all->info.screen_base)
675 of_iounmap(all->info.screen_base, all->par.fbsize);
676}
669 677
670 all = kmalloc(sizeof(*all), GFP_KERNEL); 678static int __devinit cg6_init_one(struct of_device *op)
671 if (!all) { 679{
672 printk(KERN_ERR "cg6: Cannot allocate memory.\n"); 680 struct device_node *dp = op->node;
673 return; 681 struct all_info *all;
674 } 682 int linebytes, err;
675 memset(all, 0, sizeof(*all));
676 683
677 INIT_LIST_HEAD(&all->list); 684 all = kzalloc(sizeof(*all), GFP_KERNEL);
685 if (!all)
686 return -ENOMEM;
678 687
679 spin_lock_init(&all->par.lock); 688 spin_lock_init(&all->par.lock);
680 all->par.sdev = sdev;
681 689
682 all->par.physbase = sdev->reg_addrs[0].phys_addr; 690 all->par.physbase = op->resource[0].start;
691 all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
683 692
684 sbusfb_fill_var(&all->info.var, sdev->prom_node, 8); 693 sbusfb_fill_var(&all->info.var, dp->node, 8);
685 all->info.var.red.length = 8; 694 all->info.var.red.length = 8;
686 all->info.var.green.length = 8; 695 all->info.var.green.length = 8;
687 all->info.var.blue.length = 8; 696 all->info.var.blue.length = 8;
688 697
689 linebytes = prom_getintdefault(sdev->prom_node, "linebytes", 698 linebytes = of_getintprop_default(dp, "linebytes",
690 all->info.var.xres); 699 all->info.var.xres);
691 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); 700 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
692 if (prom_getbool(sdev->prom_node, "dblbuf")) 701 if (of_find_property(dp, "dblbuf", NULL))
693 all->par.fbsize *= 4; 702 all->par.fbsize *= 4;
694 703
695 all->par.fbc = sbus_ioremap(&sdev->resource[0], CG6_FBC_OFFSET, 704 all->par.fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET,
696 4096, "cgsix fbc"); 705 4096, "cgsix fbc");
697 all->par.tec = sbus_ioremap(&sdev->resource[0], CG6_TEC_OFFSET, 706 all->par.tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET,
698 sizeof(struct cg6_tec), "cgsix tec"); 707 sizeof(struct cg6_tec), "cgsix tec");
699 all->par.thc = sbus_ioremap(&sdev->resource[0], CG6_THC_OFFSET, 708 all->par.thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET,
700 sizeof(struct cg6_thc), "cgsix thc"); 709 sizeof(struct cg6_thc), "cgsix thc");
701 all->par.bt = sbus_ioremap(&sdev->resource[0], CG6_BROOKTREE_OFFSET, 710 all->par.bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET,
702 sizeof(struct bt_regs), "cgsix dac"); 711 sizeof(struct bt_regs), "cgsix dac");
703 all->par.fhc = sbus_ioremap(&sdev->resource[0], CG6_FHC_OFFSET, 712 all->par.fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET,
704 sizeof(u32), "cgsix fhc"); 713 sizeof(u32), "cgsix fhc");
705 714
706 all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT | 715 all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
707 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT; 716 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
708 all->info.fbops = &cg6_ops; 717 all->info.fbops = &cg6_ops;
709#ifdef CONFIG_SPARC32 718
710 all->info.screen_base = (char __iomem *) 719 all->info.screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET,
711 prom_getintdefault(sdev->prom_node, "address", 0); 720 all->par.fbsize, "cgsix ram");
712#endif 721 if (!all->par.fbc || !all->par.tec || !all->par.thc ||
713 if (!all->info.screen_base) 722 !all->par.bt || !all->par.fhc || !all->info.screen_base) {
714 all->info.screen_base = 723 cg6_unmap_regs(all);
715 sbus_ioremap(&sdev->resource[0], CG6_RAM_OFFSET, 724 kfree(all);
716 all->par.fbsize, "cgsix ram"); 725 return -ENOMEM;
726 }
727
717 all->info.par = &all->par; 728 all->info.par = &all->par;
718 729
719 all->info.var.accel_flags = FB_ACCELF_TEXT; 730 all->info.var.accel_flags = FB_ACCELF_TEXT;
@@ -723,72 +734,90 @@ static void cg6_init_one(struct sbus_dev *sdev)
723 cg6_blank(0, &all->info); 734 cg6_blank(0, &all->info);
724 735
725 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { 736 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
726 printk(KERN_ERR "cg6: Could not allocate color map.\n"); 737 cg6_unmap_regs(all);
727 kfree(all); 738 kfree(all);
728 return; 739 return -ENOMEM;
729 } 740 }
730 741
731 fb_set_cmap(&all->info.cmap, &all->info); 742 fb_set_cmap(&all->info.cmap, &all->info);
732 cg6_init_fix(&all->info, linebytes); 743 cg6_init_fix(&all->info, linebytes);
733 744
734 if (register_framebuffer(&all->info) < 0) { 745 err = register_framebuffer(&all->info);
735 printk(KERN_ERR "cg6: Could not register framebuffer.\n"); 746 if (err < 0) {
747 cg6_unmap_regs(all);
736 fb_dealloc_cmap(&all->info.cmap); 748 fb_dealloc_cmap(&all->info.cmap);
737 kfree(all); 749 kfree(all);
738 return; 750 return err;
739 } 751 }
740 752
741 list_add(&all->list, &cg6_list); 753 dev_set_drvdata(&op->dev, all);
742 754
743 printk("cg6: CGsix [%s] at %lx:%lx\n", 755 printk("%s: CGsix [%s] at %lx:%lx\n",
756 dp->full_name,
744 all->info.fix.id, 757 all->info.fix.id,
745 (long) sdev->reg_addrs[0].which_io, 758 all->par.which_io, all->par.physbase);
746 (long) sdev->reg_addrs[0].phys_addr); 759
760 return 0;
747} 761}
748 762
749int __init cg6_init(void) 763static int __devinit cg6_probe(struct of_device *dev, const struct of_device_id *match)
750{ 764{
751 struct sbus_bus *sbus; 765 struct of_device *op = to_of_device(&dev->dev);
752 struct sbus_dev *sdev;
753 766
754 if (fb_get_options("cg6fb", NULL)) 767 return cg6_init_one(op);
755 return -ENODEV; 768}
756 769
757 for_all_sbusdev(sdev, sbus) { 770static int __devexit cg6_remove(struct of_device *dev)
758 if (!strcmp(sdev->prom_name, "cgsix") || 771{
759 !strcmp(sdev->prom_name, "cgthree+")) 772 struct all_info *all = dev_get_drvdata(&dev->dev);
760 cg6_init_one(sdev); 773
761 } 774 unregister_framebuffer(&all->info);
775 fb_dealloc_cmap(&all->info.cmap);
776
777 cg6_unmap_regs(all);
778
779 kfree(all);
780
781 dev_set_drvdata(&dev->dev, NULL);
762 782
763 return 0; 783 return 0;
764} 784}
765 785
766void __exit cg6_exit(void) 786static struct of_device_id cg6_match[] = {
767{ 787 {
768 struct list_head *pos, *tmp; 788 .name = "cgsix",
789 },
790 {
791 .name = "cgthree+",
792 },
793 {},
794};
795MODULE_DEVICE_TABLE(of, cg6_match);
769 796
770 list_for_each_safe(pos, tmp, &cg6_list) { 797static struct of_platform_driver cg6_driver = {
771 struct all_info *all = list_entry(pos, typeof(*all), list); 798 .name = "cg6",
799 .match_table = cg6_match,
800 .probe = cg6_probe,
801 .remove = __devexit_p(cg6_remove),
802};
772 803
773 unregister_framebuffer(&all->info); 804static int __init cg6_init(void)
774 fb_dealloc_cmap(&all->info.cmap); 805{
775 kfree(all); 806 if (fb_get_options("cg6fb", NULL))
776 } 807 return -ENODEV;
808
809 return of_register_driver(&cg6_driver, &of_bus_type);
777} 810}
778 811
779int __init 812static void __exit cg6_exit(void)
780cg6_setup(char *arg)
781{ 813{
782 /* No cmdline options yet... */ 814 of_unregister_driver(&cg6_driver);
783 return 0;
784} 815}
785 816
786module_init(cg6_init); 817module_init(cg6_init);
787
788#ifdef MODULE
789module_exit(cg6_exit); 818module_exit(cg6_exit);
790#endif
791 819
792MODULE_DESCRIPTION("framebuffer driver for CGsix chipsets"); 820MODULE_DESCRIPTION("framebuffer driver for CGsix chipsets");
793MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); 821MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
822MODULE_VERSION("2.0");
794MODULE_LICENSE("GPL"); 823MODULE_LICENSE("GPL");
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 7633e41adda1..2a0e8210d398 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -1,6 +1,6 @@
1/* ffb.c: Creator/Elite3D frame buffer driver 1/* ffb.c: Creator/Elite3D frame buffer driver
2 * 2 *
3 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 3 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz) 4 * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
5 * 5 *
6 * Driver layout based loosely on tgafb.c, see that file for credits. 6 * Driver layout based loosely on tgafb.c, see that file for credits.
@@ -19,7 +19,8 @@
19 19
20#include <asm/io.h> 20#include <asm/io.h>
21#include <asm/upa.h> 21#include <asm/upa.h>
22#include <asm/oplib.h> 22#include <asm/prom.h>
23#include <asm/of_device.h>
23#include <asm/fbio.h> 24#include <asm/fbio.h>
24 25
25#include "sbuslib.h" 26#include "sbuslib.h"
@@ -184,161 +185,161 @@ static struct fb_ops ffb_ops = {
184 185
185struct ffb_fbc { 186struct ffb_fbc {
186 /* Next vertex registers */ 187 /* Next vertex registers */
187 u32 xxx1[3]; 188 u32 xxx1[3];
188 volatile u32 alpha; 189 u32 alpha;
189 volatile u32 red; 190 u32 red;
190 volatile u32 green; 191 u32 green;
191 volatile u32 blue; 192 u32 blue;
192 volatile u32 depth; 193 u32 depth;
193 volatile u32 y; 194 u32 y;
194 volatile u32 x; 195 u32 x;
195 u32 xxx2[2]; 196 u32 xxx2[2];
196 volatile u32 ryf; 197 u32 ryf;
197 volatile u32 rxf; 198 u32 rxf;
198 u32 xxx3[2]; 199 u32 xxx3[2];
199 200
200 volatile u32 dmyf; 201 u32 dmyf;
201 volatile u32 dmxf; 202 u32 dmxf;
202 u32 xxx4[2]; 203 u32 xxx4[2];
203 volatile u32 ebyi; 204 u32 ebyi;
204 volatile u32 ebxi; 205 u32 ebxi;
205 u32 xxx5[2]; 206 u32 xxx5[2];
206 volatile u32 by; 207 u32 by;
207 volatile u32 bx; 208 u32 bx;
208 u32 dy; 209 u32 dy;
209 u32 dx; 210 u32 dx;
210 volatile u32 bh; 211 u32 bh;
211 volatile u32 bw; 212 u32 bw;
212 u32 xxx6[2]; 213 u32 xxx6[2];
213 214
214 u32 xxx7[32]; 215 u32 xxx7[32];
215 216
216 /* Setup unit vertex state register */ 217 /* Setup unit vertex state register */
217 volatile u32 suvtx; 218 u32 suvtx;
218 u32 xxx8[63]; 219 u32 xxx8[63];
219 220
220 /* Control registers */ 221 /* Control registers */
221 volatile u32 ppc; 222 u32 ppc;
222 volatile u32 wid; 223 u32 wid;
223 volatile u32 fg; 224 u32 fg;
224 volatile u32 bg; 225 u32 bg;
225 volatile u32 consty; 226 u32 consty;
226 volatile u32 constz; 227 u32 constz;
227 volatile u32 xclip; 228 u32 xclip;
228 volatile u32 dcss; 229 u32 dcss;
229 volatile u32 vclipmin; 230 u32 vclipmin;
230 volatile u32 vclipmax; 231 u32 vclipmax;
231 volatile u32 vclipzmin; 232 u32 vclipzmin;
232 volatile u32 vclipzmax; 233 u32 vclipzmax;
233 volatile u32 dcsf; 234 u32 dcsf;
234 volatile u32 dcsb; 235 u32 dcsb;
235 volatile u32 dczf; 236 u32 dczf;
236 volatile u32 dczb; 237 u32 dczb;
237 238
238 u32 xxx9; 239 u32 xxx9;
239 volatile u32 blendc; 240 u32 blendc;
240 volatile u32 blendc1; 241 u32 blendc1;
241 volatile u32 blendc2; 242 u32 blendc2;
242 volatile u32 fbramitc; 243 u32 fbramitc;
243 volatile u32 fbc; 244 u32 fbc;
244 volatile u32 rop; 245 u32 rop;
245 volatile u32 cmp; 246 u32 cmp;
246 volatile u32 matchab; 247 u32 matchab;
247 volatile u32 matchc; 248 u32 matchc;
248 volatile u32 magnab; 249 u32 magnab;
249 volatile u32 magnc; 250 u32 magnc;
250 volatile u32 fbcfg0; 251 u32 fbcfg0;
251 volatile u32 fbcfg1; 252 u32 fbcfg1;
252 volatile u32 fbcfg2; 253 u32 fbcfg2;
253 volatile u32 fbcfg3; 254 u32 fbcfg3;
254 255
255 u32 ppcfg; 256 u32 ppcfg;
256 volatile u32 pick; 257 u32 pick;
257 volatile u32 fillmode; 258 u32 fillmode;
258 volatile u32 fbramwac; 259 u32 fbramwac;
259 volatile u32 pmask; 260 u32 pmask;
260 volatile u32 xpmask; 261 u32 xpmask;
261 volatile u32 ypmask; 262 u32 ypmask;
262 volatile u32 zpmask; 263 u32 zpmask;
263 volatile u32 clip0min; 264 u32 clip0min;
264 volatile u32 clip0max; 265 u32 clip0max;
265 volatile u32 clip1min; 266 u32 clip1min;
266 volatile u32 clip1max; 267 u32 clip1max;
267 volatile u32 clip2min; 268 u32 clip2min;
268 volatile u32 clip2max; 269 u32 clip2max;
269 volatile u32 clip3min; 270 u32 clip3min;
270 volatile u32 clip3max; 271 u32 clip3max;
271 272
272 /* New 3dRAM III support regs */ 273 /* New 3dRAM III support regs */
273 volatile u32 rawblend2; 274 u32 rawblend2;
274 volatile u32 rawpreblend; 275 u32 rawpreblend;
275 volatile u32 rawstencil; 276 u32 rawstencil;
276 volatile u32 rawstencilctl; 277 u32 rawstencilctl;
277 volatile u32 threedram1; 278 u32 threedram1;
278 volatile u32 threedram2; 279 u32 threedram2;
279 volatile u32 passin; 280 u32 passin;
280 volatile u32 rawclrdepth; 281 u32 rawclrdepth;
281 volatile u32 rawpmask; 282 u32 rawpmask;
282 volatile u32 rawcsrc; 283 u32 rawcsrc;
283 volatile u32 rawmatch; 284 u32 rawmatch;
284 volatile u32 rawmagn; 285 u32 rawmagn;
285 volatile u32 rawropblend; 286 u32 rawropblend;
286 volatile u32 rawcmp; 287 u32 rawcmp;
287 volatile u32 rawwac; 288 u32 rawwac;
288 volatile u32 fbramid; 289 u32 fbramid;
289 290
290 volatile u32 drawop; 291 u32 drawop;
291 u32 xxx10[2]; 292 u32 xxx10[2];
292 volatile u32 fontlpat; 293 u32 fontlpat;
293 u32 xxx11; 294 u32 xxx11;
294 volatile u32 fontxy; 295 u32 fontxy;
295 volatile u32 fontw; 296 u32 fontw;
296 volatile u32 fontinc; 297 u32 fontinc;
297 volatile u32 font; 298 u32 font;
298 u32 xxx12[3]; 299 u32 xxx12[3];
299 volatile u32 blend2; 300 u32 blend2;
300 volatile u32 preblend; 301 u32 preblend;
301 volatile u32 stencil; 302 u32 stencil;
302 volatile u32 stencilctl; 303 u32 stencilctl;
303 304
304 u32 xxx13[4]; 305 u32 xxx13[4];
305 volatile u32 dcss1; 306 u32 dcss1;
306 volatile u32 dcss2; 307 u32 dcss2;
307 volatile u32 dcss3; 308 u32 dcss3;
308 volatile u32 widpmask; 309 u32 widpmask;
309 volatile u32 dcs2; 310 u32 dcs2;
310 volatile u32 dcs3; 311 u32 dcs3;
311 volatile u32 dcs4; 312 u32 dcs4;
312 u32 xxx14; 313 u32 xxx14;
313 volatile u32 dcd2; 314 u32 dcd2;
314 volatile u32 dcd3; 315 u32 dcd3;
315 volatile u32 dcd4; 316 u32 dcd4;
316 u32 xxx15; 317 u32 xxx15;
317 318
318 volatile u32 pattern[32]; 319 u32 pattern[32];
319 320
320 u32 xxx16[256]; 321 u32 xxx16[256];
321 322
322 volatile u32 devid; 323 u32 devid;
323 u32 xxx17[63]; 324 u32 xxx17[63];
324 325
325 volatile u32 ucsr; 326 u32 ucsr;
326 u32 xxx18[31]; 327 u32 xxx18[31];
327 328
328 volatile u32 mer; 329 u32 mer;
329}; 330};
330 331
331struct ffb_dac { 332struct ffb_dac {
332 volatile u32 type; 333 u32 type;
333 volatile u32 value; 334 u32 value;
334 volatile u32 type2; 335 u32 type2;
335 volatile u32 value2; 336 u32 value2;
336}; 337};
337 338
338struct ffb_par { 339struct ffb_par {
339 spinlock_t lock; 340 spinlock_t lock;
340 struct ffb_fbc *fbc; 341 struct ffb_fbc __iomem *fbc;
341 struct ffb_dac *dac; 342 struct ffb_dac __iomem *dac;
342 343
343 u32 flags; 344 u32 flags;
344#define FFB_FLAG_AFB 0x00000001 345#define FFB_FLAG_AFB 0x00000001
@@ -353,16 +354,13 @@ struct ffb_par {
353 unsigned long physbase; 354 unsigned long physbase;
354 unsigned long fbsize; 355 unsigned long fbsize;
355 356
356 char name[64];
357 int prom_node;
358 int prom_parent_node;
359 int dac_rev; 357 int dac_rev;
360 int board_type; 358 int board_type;
361}; 359};
362 360
363static void FFBFifo(struct ffb_par *par, int n) 361static void FFBFifo(struct ffb_par *par, int n)
364{ 362{
365 struct ffb_fbc *fbc; 363 struct ffb_fbc __iomem *fbc;
366 int cache = par->fifo_cache; 364 int cache = par->fifo_cache;
367 365
368 if (cache - n < 0) { 366 if (cache - n < 0) {
@@ -375,7 +373,7 @@ static void FFBFifo(struct ffb_par *par, int n)
375 373
376static void FFBWait(struct ffb_par *par) 374static void FFBWait(struct ffb_par *par)
377{ 375{
378 struct ffb_fbc *fbc; 376 struct ffb_fbc __iomem *fbc;
379 int limit = 10000; 377 int limit = 10000;
380 378
381 fbc = par->fbc; 379 fbc = par->fbc;
@@ -408,8 +406,8 @@ static __inline__ void ffb_rop(struct ffb_par *par, u32 rop)
408 406
409static void ffb_switch_from_graph(struct ffb_par *par) 407static void ffb_switch_from_graph(struct ffb_par *par)
410{ 408{
411 struct ffb_fbc *fbc = par->fbc; 409 struct ffb_fbc __iomem *fbc = par->fbc;
412 struct ffb_dac *dac = par->dac; 410 struct ffb_dac __iomem *dac = par->dac;
413 unsigned long flags; 411 unsigned long flags;
414 412
415 spin_lock_irqsave(&par->lock, flags); 413 spin_lock_irqsave(&par->lock, flags);
@@ -462,7 +460,7 @@ static int ffb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
462static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 460static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
463{ 461{
464 struct ffb_par *par = (struct ffb_par *) info->par; 462 struct ffb_par *par = (struct ffb_par *) info->par;
465 struct ffb_fbc *fbc = par->fbc; 463 struct ffb_fbc __iomem *fbc = par->fbc;
466 unsigned long flags; 464 unsigned long flags;
467 u32 fg; 465 u32 fg;
468 466
@@ -505,7 +503,7 @@ static void
505ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 503ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
506{ 504{
507 struct ffb_par *par = (struct ffb_par *) info->par; 505 struct ffb_par *par = (struct ffb_par *) info->par;
508 struct ffb_fbc *fbc = par->fbc; 506 struct ffb_fbc __iomem *fbc = par->fbc;
509 unsigned long flags; 507 unsigned long flags;
510 508
511 if (area->dx != area->sx || 509 if (area->dx != area->sx ||
@@ -541,7 +539,7 @@ ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
541static void ffb_imageblit(struct fb_info *info, const struct fb_image *image) 539static void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
542{ 540{
543 struct ffb_par *par = (struct ffb_par *) info->par; 541 struct ffb_par *par = (struct ffb_par *) info->par;
544 struct ffb_fbc *fbc = par->fbc; 542 struct ffb_fbc __iomem *fbc = par->fbc;
545 const u8 *data = image->data; 543 const u8 *data = image->data;
546 unsigned long flags; 544 unsigned long flags;
547 u32 fg, bg, xy; 545 u32 fg, bg, xy;
@@ -664,7 +662,7 @@ static int
664ffb_blank(int blank, struct fb_info *info) 662ffb_blank(int blank, struct fb_info *info)
665{ 663{
666 struct ffb_par *par = (struct ffb_par *) info->par; 664 struct ffb_par *par = (struct ffb_par *) info->par;
667 struct ffb_dac *dac = par->dac; 665 struct ffb_dac __iomem *dac = par->dac;
668 unsigned long flags; 666 unsigned long flags;
669 u32 tmp; 667 u32 tmp;
670 668
@@ -883,78 +881,42 @@ ffb_init_fix(struct fb_info *info)
883 info->fix.accel = FB_ACCEL_SUN_CREATOR; 881 info->fix.accel = FB_ACCEL_SUN_CREATOR;
884} 882}
885 883
886static int ffb_apply_upa_parent_ranges(int parent,
887 struct linux_prom64_registers *regs)
888{
889 struct linux_prom64_ranges ranges[PROMREG_MAX];
890 char name[128];
891 int len, i;
892
893 prom_getproperty(parent, "name", name, sizeof(name));
894 if (strcmp(name, "upa") != 0)
895 return 0;
896
897 len = prom_getproperty(parent, "ranges", (void *) ranges, sizeof(ranges));
898 if (len <= 0)
899 return 1;
900
901 len /= sizeof(struct linux_prom64_ranges);
902 for (i = 0; i < len; i++) {
903 struct linux_prom64_ranges *rng = &ranges[i];
904 u64 phys_addr = regs->phys_addr;
905
906 if (phys_addr >= rng->ot_child_base &&
907 phys_addr < (rng->ot_child_base + rng->or_size)) {
908 regs->phys_addr -= rng->ot_child_base;
909 regs->phys_addr += rng->ot_parent_base;
910 return 0;
911 }
912 }
913
914 return 1;
915}
916
917struct all_info { 884struct all_info {
918 struct fb_info info; 885 struct fb_info info;
919 struct ffb_par par; 886 struct ffb_par par;
920 u32 pseudo_palette[256]; 887 u32 pseudo_palette[256];
921 struct list_head list;
922}; 888};
923static LIST_HEAD(ffb_list);
924 889
925static void ffb_init_one(int node, int parent) 890static int ffb_init_one(struct of_device *op)
926{ 891{
927 struct linux_prom64_registers regs[2*PROMREG_MAX]; 892 struct device_node *dp = op->node;
928 struct ffb_fbc *fbc; 893 struct ffb_fbc __iomem *fbc;
929 struct ffb_dac *dac; 894 struct ffb_dac __iomem *dac;
930 struct all_info *all; 895 struct all_info *all;
896 int err;
931 897
932 if (prom_getproperty(node, "reg", (void *) regs, sizeof(regs)) <= 0) { 898 all = kzalloc(sizeof(*all), GFP_KERNEL);
933 printk("ffb: Cannot get reg device node property.\n"); 899 if (!all)
934 return; 900 return -ENOMEM;
935 }
936 901
937 if (ffb_apply_upa_parent_ranges(parent, &regs[0])) { 902 spin_lock_init(&all->par.lock);
938 printk("ffb: Cannot apply parent ranges to regs.\n"); 903 all->par.fbc = of_ioremap(&op->resource[2], 0,
939 return; 904 sizeof(struct ffb_fbc), "ffb fbc");
905 if (!all->par.fbc) {
906 kfree(all);
907 return -ENOMEM;
940 } 908 }
941 909
942 all = kmalloc(sizeof(*all), GFP_KERNEL); 910 all->par.dac = of_ioremap(&op->resource[1], 0,
943 if (!all) { 911 sizeof(struct ffb_dac), "ffb dac");
944 printk(KERN_ERR "ffb: Cannot allocate memory.\n"); 912 if (!all->par.dac) {
945 return; 913 of_iounmap(all->par.fbc, sizeof(struct ffb_fbc));
914 kfree(all);
915 return -ENOMEM;
946 } 916 }
947 memset(all, 0, sizeof(*all));
948
949 INIT_LIST_HEAD(&all->list);
950 917
951 spin_lock_init(&all->par.lock);
952 all->par.fbc = (struct ffb_fbc *)(regs[0].phys_addr + FFB_FBC_REGS_POFF);
953 all->par.dac = (struct ffb_dac *)(regs[0].phys_addr + FFB_DAC_POFF);
954 all->par.rop_cache = FFB_ROP_NEW; 918 all->par.rop_cache = FFB_ROP_NEW;
955 all->par.physbase = regs[0].phys_addr; 919 all->par.physbase = op->resource[0].start;
956 all->par.prom_node = node;
957 all->par.prom_parent_node = parent;
958 920
959 /* Don't mention copyarea, so SCROLL_REDRAW is always 921 /* Don't mention copyarea, so SCROLL_REDRAW is always
960 * used. It is the fastest on this chip. 922 * used. It is the fastest on this chip.
@@ -968,7 +930,7 @@ static void ffb_init_one(int node, int parent)
968 all->info.par = &all->par; 930 all->info.par = &all->par;
969 all->info.pseudo_palette = all->pseudo_palette; 931 all->info.pseudo_palette = all->pseudo_palette;
970 932
971 sbusfb_fill_var(&all->info.var, all->par.prom_node, 32); 933 sbusfb_fill_var(&all->info.var, dp->node, 32);
972 all->par.fbsize = PAGE_ALIGN(all->info.var.xres * 934 all->par.fbsize = PAGE_ALIGN(all->info.var.xres *
973 all->info.var.yres * 935 all->info.var.yres *
974 4); 936 4);
@@ -976,14 +938,13 @@ static void ffb_init_one(int node, int parent)
976 938
977 all->info.var.accel_flags = FB_ACCELF_TEXT; 939 all->info.var.accel_flags = FB_ACCELF_TEXT;
978 940
979 prom_getstring(node, "name", all->par.name, sizeof(all->par.name)); 941 if (!strcmp(dp->name, "SUNW,afb"))
980 if (!strcmp(all->par.name, "SUNW,afb"))
981 all->par.flags |= FFB_FLAG_AFB; 942 all->par.flags |= FFB_FLAG_AFB;
982 943
983 all->par.board_type = prom_getintdefault(node, "board_type", 0); 944 all->par.board_type = of_getintprop_default(dp, "board_type", 0);
984 945
985 fbc = all->par.fbc; 946 fbc = all->par.fbc;
986 if((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) 947 if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
987 upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr); 948 upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
988 949
989 ffb_switch_from_graph(&all->par); 950 ffb_switch_from_graph(&all->par);
@@ -1008,81 +969,88 @@ static void ffb_init_one(int node, int parent)
1008 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { 969 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
1009 printk(KERN_ERR "ffb: Could not allocate color map.\n"); 970 printk(KERN_ERR "ffb: Could not allocate color map.\n");
1010 kfree(all); 971 kfree(all);
1011 return; 972 return -ENOMEM;
1012 } 973 }
1013 974
1014 ffb_init_fix(&all->info); 975 ffb_init_fix(&all->info);
1015 976
1016 if (register_framebuffer(&all->info) < 0) { 977 err = register_framebuffer(&all->info);
978 if (err < 0) {
1017 printk(KERN_ERR "ffb: Could not register framebuffer.\n"); 979 printk(KERN_ERR "ffb: Could not register framebuffer.\n");
1018 fb_dealloc_cmap(&all->info.cmap); 980 fb_dealloc_cmap(&all->info.cmap);
1019 kfree(all); 981 kfree(all);
1020 return; 982 return err;
1021 } 983 }
1022 984
1023 list_add(&all->list, &ffb_list); 985 dev_set_drvdata(&op->dev, all);
1024 986
1025 printk("ffb: %s at %016lx type %d DAC %d\n", 987 printk("%s: %s at %016lx, type %d, DAC revision %d\n",
988 dp->full_name,
1026 ((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"), 989 ((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
1027 regs[0].phys_addr, all->par.board_type, all->par.dac_rev); 990 all->par.physbase, all->par.board_type, all->par.dac_rev);
991
992 return 0;
1028} 993}
1029 994
1030static void ffb_scan_siblings(int root) 995static int __devinit ffb_probe(struct of_device *dev, const struct of_device_id *match)
1031{ 996{
1032 int node, child; 997 struct of_device *op = to_of_device(&dev->dev);
1033 998
1034 child = prom_getchild(root); 999 return ffb_init_one(op);
1035 for (node = prom_searchsiblings(child, "SUNW,ffb"); node;
1036 node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb"))
1037 ffb_init_one(node, root);
1038 for (node = prom_searchsiblings(child, "SUNW,afb"); node;
1039 node = prom_searchsiblings(prom_getsibling(node), "SUNW,afb"))
1040 ffb_init_one(node, root);
1041} 1000}
1042 1001
1043int __init ffb_init(void) 1002static int __devexit ffb_remove(struct of_device *dev)
1044{ 1003{
1045 int root; 1004 struct all_info *all = dev_get_drvdata(&dev->dev);
1046 1005
1047 if (fb_get_options("ffb", NULL)) 1006 unregister_framebuffer(&all->info);
1048 return -ENODEV; 1007 fb_dealloc_cmap(&all->info.cmap);
1049 1008
1050 ffb_scan_siblings(prom_root_node); 1009 of_iounmap(all->par.fbc, sizeof(struct ffb_fbc));
1010 of_iounmap(all->par.dac, sizeof(struct ffb_dac));
1051 1011
1052 root = prom_getchild(prom_root_node); 1012 kfree(all);
1053 for (root = prom_searchsiblings(root, "upa"); root; 1013
1054 root = prom_searchsiblings(prom_getsibling(root), "upa")) 1014 dev_set_drvdata(&dev->dev, NULL);
1055 ffb_scan_siblings(root);
1056 1015
1057 return 0; 1016 return 0;
1058} 1017}
1059 1018
1060void __exit ffb_exit(void) 1019static struct of_device_id ffb_match[] = {
1061{ 1020 {
1062 struct list_head *pos, *tmp; 1021 .name = "SUNW,ffb",
1022 },
1023 {
1024 .name = "SUNW,afb",
1025 },
1026 {},
1027};
1028MODULE_DEVICE_TABLE(of, ffb_match);
1029
1030static struct of_platform_driver ffb_driver = {
1031 .name = "ffb",
1032 .match_table = ffb_match,
1033 .probe = ffb_probe,
1034 .remove = __devexit_p(ffb_remove),
1035};
1063 1036
1064 list_for_each_safe(pos, tmp, &ffb_list) { 1037int __init ffb_init(void)
1065 struct all_info *all = list_entry(pos, typeof(*all), list); 1038{
1039 if (fb_get_options("ffb", NULL))
1040 return -ENODEV;
1066 1041
1067 unregister_framebuffer(&all->info); 1042 return of_register_driver(&ffb_driver, &of_bus_type);
1068 fb_dealloc_cmap(&all->info.cmap);
1069 kfree(all);
1070 }
1071} 1043}
1072 1044
1073int __init 1045void __exit ffb_exit(void)
1074ffb_setup(char *arg)
1075{ 1046{
1076 /* No cmdline options yet... */ 1047 of_unregister_driver(&ffb_driver);
1077 return 0;
1078} 1048}
1079 1049
1080module_init(ffb_init); 1050module_init(ffb_init);
1081
1082#ifdef MODULE
1083module_exit(ffb_exit); 1051module_exit(ffb_exit);
1084#endif
1085 1052
1086MODULE_DESCRIPTION("framebuffer driver for Creator/Elite3D chipsets"); 1053MODULE_DESCRIPTION("framebuffer driver for Creator/Elite3D chipsets");
1087MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); 1054MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
1055MODULE_VERSION("2.0");
1088MODULE_LICENSE("GPL"); 1056MODULE_LICENSE("GPL");
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index a23cfdb9d826..f3a24338d9ac 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -1,6 +1,6 @@
1/* leo.c: LEO frame buffer driver 1/* leo.c: LEO frame buffer driver
2 * 2 *
3 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 3 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz) 4 * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
5 * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz) 5 * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
6 * 6 *
@@ -18,8 +18,8 @@
18#include <linux/mm.h> 18#include <linux/mm.h>
19 19
20#include <asm/io.h> 20#include <asm/io.h>
21#include <asm/sbus.h> 21#include <asm/prom.h>
22#include <asm/oplib.h> 22#include <asm/of_device.h>
23#include <asm/fbio.h> 23#include <asm/fbio.h>
24 24
25#include "sbuslib.h" 25#include "sbuslib.h"
@@ -80,10 +80,10 @@ static struct fb_ops leo_ops = {
80 80
81struct leo_cursor { 81struct leo_cursor {
82 u8 xxx0[16]; 82 u8 xxx0[16];
83 volatile u32 cur_type; 83 u32 cur_type;
84 volatile u32 cur_misc; 84 u32 cur_misc;
85 volatile u32 cur_cursxy; 85 u32 cur_cursxy;
86 volatile u32 cur_data; 86 u32 cur_data;
87}; 87};
88 88
89#define LEO_KRN_TYPE_CLUT0 0x00001000 89#define LEO_KRN_TYPE_CLUT0 0x00001000
@@ -99,27 +99,27 @@ struct leo_cursor {
99#define LEO_KRN_CSR_UNK2 0x00000001 99#define LEO_KRN_CSR_UNK2 0x00000001
100 100
101struct leo_lx_krn { 101struct leo_lx_krn {
102 volatile u32 krn_type; 102 u32 krn_type;
103 volatile u32 krn_csr; 103 u32 krn_csr;
104 volatile u32 krn_value; 104 u32 krn_value;
105}; 105};
106 106
107struct leo_lc_ss0_krn { 107struct leo_lc_ss0_krn {
108 volatile u32 misc; 108 u32 misc;
109 u8 xxx0[0x800-4]; 109 u8 xxx0[0x800-4];
110 volatile u32 rev; 110 u32 rev;
111}; 111};
112 112
113struct leo_lc_ss0_usr { 113struct leo_lc_ss0_usr {
114 volatile u32 csr; 114 u32 csr;
115 volatile u32 addrspace; 115 u32 addrspace;
116 volatile u32 fontmsk; 116 u32 fontmsk;
117 volatile u32 fontt; 117 u32 fontt;
118 volatile u32 extent; 118 u32 extent;
119 volatile u32 src; 119 u32 src;
120 u32 dst; 120 u32 dst;
121 volatile u32 copy; 121 u32 copy;
122 volatile u32 fill; 122 u32 fill;
123}; 123};
124 124
125struct leo_lc_ss1_krn { 125struct leo_lc_ss1_krn {
@@ -132,47 +132,47 @@ struct leo_lc_ss1_usr {
132 132
133struct leo_ld { 133struct leo_ld {
134 u8 xxx0[0xe00]; 134 u8 xxx0[0xe00];
135 volatile u32 csr; 135 u32 csr;
136 volatile u32 wid; 136 u32 wid;
137 volatile u32 wmask; 137 u32 wmask;
138 volatile u32 widclip; 138 u32 widclip;
139 volatile u32 vclipmin; 139 u32 vclipmin;
140 volatile u32 vclipmax; 140 u32 vclipmax;
141 volatile u32 pickmin; /* SS1 only */ 141 u32 pickmin; /* SS1 only */
142 volatile u32 pickmax; /* SS1 only */ 142 u32 pickmax; /* SS1 only */
143 volatile u32 fg; 143 u32 fg;
144 volatile u32 bg; 144 u32 bg;
145 volatile u32 src; /* Copy/Scroll (SS0 only) */ 145 u32 src; /* Copy/Scroll (SS0 only) */
146 volatile u32 dst; /* Copy/Scroll/Fill (SS0 only) */ 146 u32 dst; /* Copy/Scroll/Fill (SS0 only) */
147 volatile u32 extent; /* Copy/Scroll/Fill size (SS0 only) */ 147 u32 extent; /* Copy/Scroll/Fill size (SS0 only) */
148 u32 xxx1[3]; 148 u32 xxx1[3];
149 volatile u32 setsem; /* SS1 only */ 149 u32 setsem; /* SS1 only */
150 volatile u32 clrsem; /* SS1 only */ 150 u32 clrsem; /* SS1 only */
151 volatile u32 clrpick; /* SS1 only */ 151 u32 clrpick; /* SS1 only */
152 volatile u32 clrdat; /* SS1 only */ 152 u32 clrdat; /* SS1 only */
153 volatile u32 alpha; /* SS1 only */ 153 u32 alpha; /* SS1 only */
154 u8 xxx2[0x2c]; 154 u8 xxx2[0x2c];
155 volatile u32 winbg; 155 u32 winbg;
156 volatile u32 planemask; 156 u32 planemask;
157 volatile u32 rop; 157 u32 rop;
158 volatile u32 z; 158 u32 z;
159 volatile u32 dczf; /* SS1 only */ 159 u32 dczf; /* SS1 only */
160 volatile u32 dczb; /* SS1 only */ 160 u32 dczb; /* SS1 only */
161 volatile u32 dcs; /* SS1 only */ 161 u32 dcs; /* SS1 only */
162 volatile u32 dczs; /* SS1 only */ 162 u32 dczs; /* SS1 only */
163 volatile u32 pickfb; /* SS1 only */ 163 u32 pickfb; /* SS1 only */
164 volatile u32 pickbb; /* SS1 only */ 164 u32 pickbb; /* SS1 only */
165 volatile u32 dcfc; /* SS1 only */ 165 u32 dcfc; /* SS1 only */
166 volatile u32 forcecol; /* SS1 only */ 166 u32 forcecol; /* SS1 only */
167 volatile u32 door[8]; /* SS1 only */ 167 u32 door[8]; /* SS1 only */
168 volatile u32 pick[5]; /* SS1 only */ 168 u32 pick[5]; /* SS1 only */
169}; 169};
170 170
171#define LEO_SS1_MISC_ENABLE 0x00000001 171#define LEO_SS1_MISC_ENABLE 0x00000001
172#define LEO_SS1_MISC_STEREO 0x00000002 172#define LEO_SS1_MISC_STEREO 0x00000002
173struct leo_ld_ss1 { 173struct leo_ld_ss1 {
174 u8 xxx0[0xef4]; 174 u8 xxx0[0xef4];
175 volatile u32 ss1_misc; 175 u32 ss1_misc;
176}; 176};
177 177
178struct leo_ld_gbl { 178struct leo_ld_gbl {
@@ -193,9 +193,8 @@ struct leo_par {
193#define LEO_FLAG_BLANKED 0x00000001 193#define LEO_FLAG_BLANKED 0x00000001
194 194
195 unsigned long physbase; 195 unsigned long physbase;
196 unsigned long which_io;
196 unsigned long fbsize; 197 unsigned long fbsize;
197
198 struct sbus_dev *sdev;
199}; 198};
200 199
201static void leo_wait(struct leo_lx_krn __iomem *lx_krn) 200static void leo_wait(struct leo_lx_krn __iomem *lx_krn)
@@ -368,8 +367,7 @@ static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma)
368 367
369 return sbusfb_mmap_helper(leo_mmap_map, 368 return sbusfb_mmap_helper(leo_mmap_map,
370 par->physbase, par->fbsize, 369 par->physbase, par->fbsize,
371 par->sdev->reg_addrs[0].which_io, 370 par->which_io, vma);
372 vma);
373} 371}
374 372
375static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) 373static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
@@ -385,11 +383,9 @@ static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
385 */ 383 */
386 384
387static void 385static void
388leo_init_fix(struct fb_info *info) 386leo_init_fix(struct fb_info *info, struct device_node *dp)
389{ 387{
390 struct leo_par *par = (struct leo_par *)info->par; 388 strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
391
392 strlcpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id));
393 389
394 info->fix.type = FB_TYPE_PACKED_PIXELS; 390 info->fix.type = FB_TYPE_PACKED_PIXELS;
395 info->fix.visual = FB_VISUAL_TRUECOLOR; 391 info->fix.visual = FB_VISUAL_TRUECOLOR;
@@ -532,60 +528,74 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
532struct all_info { 528struct all_info {
533 struct fb_info info; 529 struct fb_info info;
534 struct leo_par par; 530 struct leo_par par;
535 struct list_head list;
536}; 531};
537static LIST_HEAD(leo_list);
538 532
539static void leo_init_one(struct sbus_dev *sdev) 533static void leo_unmap_regs(struct all_info *all)
540{ 534{
541 struct all_info *all; 535 if (all->par.lc_ss0_usr)
542 int linebytes; 536 of_iounmap(all->par.lc_ss0_usr, 0x1000);
537 if (all->par.ld_ss0)
538 of_iounmap(all->par.ld_ss0, 0x1000);
539 if (all->par.ld_ss1)
540 of_iounmap(all->par.ld_ss1, 0x1000);
541 if (all->par.lx_krn)
542 of_iounmap(all->par.lx_krn, 0x1000);
543 if (all->par.cursor)
544 of_iounmap(all->par.cursor, sizeof(struct leo_cursor));
545 if (all->info.screen_base)
546 of_iounmap(all->info.screen_base, 0x800000);
547}
543 548
544 all = kmalloc(sizeof(*all), GFP_KERNEL); 549static int __devinit leo_init_one(struct of_device *op)
545 if (!all) { 550{
546 printk(KERN_ERR "leo: Cannot allocate memory.\n"); 551 struct device_node *dp = op->node;
547 return; 552 struct all_info *all;
548 } 553 int linebytes, err;
549 memset(all, 0, sizeof(*all));
550 554
551 INIT_LIST_HEAD(&all->list); 555 all = kzalloc(sizeof(*all), GFP_KERNEL);
556 if (!all)
557 return -ENOMEM;
552 558
553 spin_lock_init(&all->par.lock); 559 spin_lock_init(&all->par.lock);
554 all->par.sdev = sdev;
555 560
556 all->par.physbase = sdev->reg_addrs[0].phys_addr; 561 all->par.physbase = op->resource[0].start;
562 all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
557 563
558 sbusfb_fill_var(&all->info.var, sdev->prom_node, 32); 564 sbusfb_fill_var(&all->info.var, dp->node, 32);
559 leo_fixup_var_rgb(&all->info.var); 565 leo_fixup_var_rgb(&all->info.var);
560 566
561 linebytes = prom_getintdefault(sdev->prom_node, "linebytes", 567 linebytes = of_getintprop_default(dp, "linebytes",
562 all->info.var.xres); 568 all->info.var.xres);
563 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); 569 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
564 570
565#ifdef CONFIG_SPARC32
566 all->info.screen_base = (char __iomem *)
567 prom_getintdefault(sdev->prom_node, "address", 0);
568#endif
569 if (!all->info.screen_base)
570 all->info.screen_base =
571 sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0,
572 0x800000, "leo ram");
573
574 all->par.lc_ss0_usr = 571 all->par.lc_ss0_usr =
575 sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR, 572 of_ioremap(&op->resource[0], LEO_OFF_LC_SS0_USR,
576 0x1000, "leolc ss0usr"); 573 0x1000, "leolc ss0usr");
577 all->par.ld_ss0 = 574 all->par.ld_ss0 =
578 sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0, 575 of_ioremap(&op->resource[0], LEO_OFF_LD_SS0,
579 0x1000, "leold ss0"); 576 0x1000, "leold ss0");
580 all->par.ld_ss1 = 577 all->par.ld_ss1 =
581 sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1, 578 of_ioremap(&op->resource[0], LEO_OFF_LD_SS1,
582 0x1000, "leold ss1"); 579 0x1000, "leold ss1");
583 all->par.lx_krn = 580 all->par.lx_krn =
584 sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN, 581 of_ioremap(&op->resource[0], LEO_OFF_LX_KRN,
585 0x1000, "leolx krn"); 582 0x1000, "leolx krn");
586 all->par.cursor = 583 all->par.cursor =
587 sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR, 584 of_ioremap(&op->resource[0], LEO_OFF_LX_CURSOR,
588 sizeof(struct leo_cursor), "leolx cursor"); 585 sizeof(struct leo_cursor), "leolx cursor");
586 all->info.screen_base =
587 of_ioremap(&op->resource[0], LEO_OFF_SS0,
588 0x800000, "leo ram");
589 if (!all->par.lc_ss0_usr ||
590 !all->par.ld_ss0 ||
591 !all->par.ld_ss1 ||
592 !all->par.lx_krn ||
593 !all->par.cursor ||
594 !all->info.screen_base) {
595 leo_unmap_regs(all);
596 kfree(all);
597 return -ENOMEM;
598 }
589 599
590 all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 600 all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
591 all->info.fbops = &leo_ops; 601 all->info.fbops = &leo_ops;
@@ -597,69 +607,85 @@ static void leo_init_one(struct sbus_dev *sdev)
597 leo_blank(0, &all->info); 607 leo_blank(0, &all->info);
598 608
599 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { 609 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
600 printk(KERN_ERR "leo: Could not allocate color map.\n"); 610 leo_unmap_regs(all);
601 kfree(all); 611 kfree(all);
602 return; 612 return -ENOMEM;;
603 } 613 }
604 614
605 leo_init_fix(&all->info); 615 leo_init_fix(&all->info, dp);
606 616
607 if (register_framebuffer(&all->info) < 0) { 617 err = register_framebuffer(&all->info);
608 printk(KERN_ERR "leo: Could not register framebuffer.\n"); 618 if (err < 0) {
609 fb_dealloc_cmap(&all->info.cmap); 619 fb_dealloc_cmap(&all->info.cmap);
620 leo_unmap_regs(all);
610 kfree(all); 621 kfree(all);
611 return; 622 return err;
612 } 623 }
613 624
614 list_add(&all->list, &leo_list); 625 dev_set_drvdata(&op->dev, all);
626
627 printk("%s: leo at %lx:%lx\n",
628 dp->full_name,
629 all->par.which_io, all->par.physbase);
615 630
616 printk("leo: %s at %lx:%lx\n", 631 return 0;
617 sdev->prom_name,
618 (long) sdev->reg_addrs[0].which_io,
619 (long) sdev->reg_addrs[0].phys_addr);
620} 632}
621 633
622int __init leo_init(void) 634static int __devinit leo_probe(struct of_device *dev, const struct of_device_id *match)
623{ 635{
624 struct sbus_bus *sbus; 636 struct of_device *op = to_of_device(&dev->dev);
625 struct sbus_dev *sdev;
626 637
627 if (fb_get_options("leofb", NULL)) 638 return leo_init_one(op);
628 return -ENODEV; 639}
629 640
630 for_all_sbusdev(sdev, sbus) { 641static int __devexit leo_remove(struct of_device *dev)
631 if (!strcmp(sdev->prom_name, "leo")) 642{
632 leo_init_one(sdev); 643 struct all_info *all = dev_get_drvdata(&dev->dev);
633 } 644
645 unregister_framebuffer(&all->info);
646 fb_dealloc_cmap(&all->info.cmap);
647
648 leo_unmap_regs(all);
649
650 kfree(all);
651
652 dev_set_drvdata(&dev->dev, NULL);
634 653
635 return 0; 654 return 0;
636} 655}
637 656
638void __exit leo_exit(void) 657static struct of_device_id leo_match[] = {
639{ 658 {
640 struct list_head *pos, *tmp; 659 .name = "leo",
660 },
661 {},
662};
663MODULE_DEVICE_TABLE(of, leo_match);
664
665static struct of_platform_driver leo_driver = {
666 .name = "leo",
667 .match_table = leo_match,
668 .probe = leo_probe,
669 .remove = __devexit_p(leo_remove),
670};
641 671
642 list_for_each_safe(pos, tmp, &leo_list) { 672static int __init leo_init(void)
643 struct all_info *all = list_entry(pos, typeof(*all), list); 673{
674 if (fb_get_options("leofb", NULL))
675 return -ENODEV;
644 676
645 unregister_framebuffer(&all->info); 677 return of_register_driver(&leo_driver, &of_bus_type);
646 fb_dealloc_cmap(&all->info.cmap);
647 kfree(all);
648 }
649} 678}
650 679
651int __init 680static void __exit leo_exit(void)
652leo_setup(char *arg)
653{ 681{
654 /* No cmdline options yet... */ 682 of_unregister_driver(&leo_driver);
655 return 0;
656} 683}
657 684
658module_init(leo_init); 685module_init(leo_init);
659#ifdef MODULE
660module_exit(leo_exit); 686module_exit(leo_exit);
661#endif
662 687
663MODULE_DESCRIPTION("framebuffer driver for LEO chipsets"); 688MODULE_DESCRIPTION("framebuffer driver for LEO chipsets");
664MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); 689MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
690MODULE_VERSION("2.0");
665MODULE_LICENSE("GPL"); 691MODULE_LICENSE("GPL");
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index 0d1957505359..56ac51d6a7f3 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -1,6 +1,6 @@
1/* p9100.c: P9100 frame buffer driver 1/* p9100.c: P9100 frame buffer driver
2 * 2 *
3 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 3 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
4 * Copyright 1999 Derrick J Brashear (shadow@dementia.org) 4 * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
5 * 5 *
6 * Driver layout based loosely on tgafb.c, see that file for credits. 6 * Driver layout based loosely on tgafb.c, see that file for credits.
@@ -17,8 +17,8 @@
17#include <linux/mm.h> 17#include <linux/mm.h>
18 18
19#include <asm/io.h> 19#include <asm/io.h>
20#include <asm/sbus.h> 20#include <asm/prom.h>
21#include <asm/oplib.h> 21#include <asm/of_device.h>
22#include <asm/fbio.h> 22#include <asm/fbio.h>
23 23
24#include "sbuslib.h" 24#include "sbuslib.h"
@@ -72,60 +72,60 @@ static struct fb_ops p9100_ops = {
72 72
73struct p9100_regs { 73struct p9100_regs {
74 /* Registers for the system control */ 74 /* Registers for the system control */
75 volatile u32 sys_base; 75 u32 sys_base;
76 volatile u32 sys_config; 76 u32 sys_config;
77 volatile u32 sys_intr; 77 u32 sys_intr;
78 volatile u32 sys_int_ena; 78 u32 sys_int_ena;
79 volatile u32 sys_alt_rd; 79 u32 sys_alt_rd;
80 volatile u32 sys_alt_wr; 80 u32 sys_alt_wr;
81 volatile u32 sys_xxx[58]; 81 u32 sys_xxx[58];
82 82
83 /* Registers for the video control */ 83 /* Registers for the video control */
84 volatile u32 vid_base; 84 u32 vid_base;
85 volatile u32 vid_hcnt; 85 u32 vid_hcnt;
86 volatile u32 vid_htotal; 86 u32 vid_htotal;
87 volatile u32 vid_hsync_rise; 87 u32 vid_hsync_rise;
88 volatile u32 vid_hblank_rise; 88 u32 vid_hblank_rise;
89 volatile u32 vid_hblank_fall; 89 u32 vid_hblank_fall;
90 volatile u32 vid_hcnt_preload; 90 u32 vid_hcnt_preload;
91 volatile u32 vid_vcnt; 91 u32 vid_vcnt;
92 volatile u32 vid_vlen; 92 u32 vid_vlen;
93 volatile u32 vid_vsync_rise; 93 u32 vid_vsync_rise;
94 volatile u32 vid_vblank_rise; 94 u32 vid_vblank_rise;
95 volatile u32 vid_vblank_fall; 95 u32 vid_vblank_fall;
96 volatile u32 vid_vcnt_preload; 96 u32 vid_vcnt_preload;
97 volatile u32 vid_screenpaint_addr; 97 u32 vid_screenpaint_addr;
98 volatile u32 vid_screenpaint_timectl1; 98 u32 vid_screenpaint_timectl1;
99 volatile u32 vid_screenpaint_qsfcnt; 99 u32 vid_screenpaint_qsfcnt;
100 volatile u32 vid_screenpaint_timectl2; 100 u32 vid_screenpaint_timectl2;
101 volatile u32 vid_xxx[15]; 101 u32 vid_xxx[15];
102 102
103 /* Registers for the video control */ 103 /* Registers for the video control */
104 volatile u32 vram_base; 104 u32 vram_base;
105 volatile u32 vram_memcfg; 105 u32 vram_memcfg;
106 volatile u32 vram_refresh_pd; 106 u32 vram_refresh_pd;
107 volatile u32 vram_refresh_cnt; 107 u32 vram_refresh_cnt;
108 volatile u32 vram_raslo_max; 108 u32 vram_raslo_max;
109 volatile u32 vram_raslo_cur; 109 u32 vram_raslo_cur;
110 volatile u32 pwrup_cfg; 110 u32 pwrup_cfg;
111 volatile u32 vram_xxx[25]; 111 u32 vram_xxx[25];
112 112
113 /* Registers for IBM RGB528 Palette */ 113 /* Registers for IBM RGB528 Palette */
114 volatile u32 ramdac_cmap_wridx; 114 u32 ramdac_cmap_wridx;
115 volatile u32 ramdac_palette_data; 115 u32 ramdac_palette_data;
116 volatile u32 ramdac_pixel_mask; 116 u32 ramdac_pixel_mask;
117 volatile u32 ramdac_palette_rdaddr; 117 u32 ramdac_palette_rdaddr;
118 volatile u32 ramdac_idx_lo; 118 u32 ramdac_idx_lo;
119 volatile u32 ramdac_idx_hi; 119 u32 ramdac_idx_hi;
120 volatile u32 ramdac_idx_data; 120 u32 ramdac_idx_data;
121 volatile u32 ramdac_idx_ctl; 121 u32 ramdac_idx_ctl;
122 volatile u32 ramdac_xxx[1784]; 122 u32 ramdac_xxx[1784];
123}; 123};
124 124
125struct p9100_cmd_parameng { 125struct p9100_cmd_parameng {
126 volatile u32 parameng_status; 126 u32 parameng_status;
127 volatile u32 parameng_bltcmd; 127 u32 parameng_bltcmd;
128 volatile u32 parameng_quadcmd; 128 u32 parameng_quadcmd;
129}; 129};
130 130
131struct p9100_par { 131struct p9100_par {
@@ -136,9 +136,8 @@ struct p9100_par {
136#define P9100_FLAG_BLANKED 0x00000001 136#define P9100_FLAG_BLANKED 0x00000001
137 137
138 unsigned long physbase; 138 unsigned long physbase;
139 unsigned long which_io;
139 unsigned long fbsize; 140 unsigned long fbsize;
140
141 struct sbus_dev *sdev;
142}; 141};
143 142
144/** 143/**
@@ -227,8 +226,7 @@ static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma)
227 226
228 return sbusfb_mmap_helper(p9100_mmap_map, 227 return sbusfb_mmap_helper(p9100_mmap_map,
229 par->physbase, par->fbsize, 228 par->physbase, par->fbsize,
230 par->sdev->reg_addrs[0].which_io, 229 par->which_io, vma);
231 vma);
232} 230}
233 231
234static int p9100_ioctl(struct fb_info *info, unsigned int cmd, 232static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
@@ -245,12 +243,9 @@ static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
245 * Initialisation 243 * Initialisation
246 */ 244 */
247 245
248static void 246static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
249p9100_init_fix(struct fb_info *info, int linebytes)
250{ 247{
251 struct p9100_par *par = (struct p9100_par *)info->par; 248 strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
252
253 strlcpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id));
254 249
255 info->fix.type = FB_TYPE_PACKED_PIXELS; 250 info->fix.type = FB_TYPE_PACKED_PIXELS;
256 info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 251 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -263,121 +258,137 @@ p9100_init_fix(struct fb_info *info, int linebytes)
263struct all_info { 258struct all_info {
264 struct fb_info info; 259 struct fb_info info;
265 struct p9100_par par; 260 struct p9100_par par;
266 struct list_head list;
267}; 261};
268static LIST_HEAD(p9100_list);
269 262
270static void p9100_init_one(struct sbus_dev *sdev) 263static int __devinit p9100_init_one(struct of_device *op)
271{ 264{
265 struct device_node *dp = op->node;
272 struct all_info *all; 266 struct all_info *all;
273 int linebytes; 267 int linebytes, err;
274
275 all = kmalloc(sizeof(*all), GFP_KERNEL);
276 if (!all) {
277 printk(KERN_ERR "p9100: Cannot allocate memory.\n");
278 return;
279 }
280 memset(all, 0, sizeof(*all));
281 268
282 INIT_LIST_HEAD(&all->list); 269 all = kzalloc(sizeof(*all), GFP_KERNEL);
270 if (!all)
271 return -ENOMEM;
283 272
284 spin_lock_init(&all->par.lock); 273 spin_lock_init(&all->par.lock);
285 all->par.sdev = sdev;
286 274
287 /* This is the framebuffer and the only resource apps can mmap. */ 275 /* This is the framebuffer and the only resource apps can mmap. */
288 all->par.physbase = sdev->reg_addrs[2].phys_addr; 276 all->par.physbase = op->resource[2].start;
277 all->par.which_io = op->resource[2].flags & IORESOURCE_BITS;
289 278
290 sbusfb_fill_var(&all->info.var, sdev->prom_node, 8); 279 sbusfb_fill_var(&all->info.var, dp->node, 8);
291 all->info.var.red.length = 8; 280 all->info.var.red.length = 8;
292 all->info.var.green.length = 8; 281 all->info.var.green.length = 8;
293 all->info.var.blue.length = 8; 282 all->info.var.blue.length = 8;
294 283
295 linebytes = prom_getintdefault(sdev->prom_node, "linebytes", 284 linebytes = of_getintprop_default(dp, "linebytes",
296 all->info.var.xres); 285 all->info.var.xres);
297 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); 286 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
298 287
299 all->par.regs = sbus_ioremap(&sdev->resource[0], 0, 288 all->par.regs = of_ioremap(&op->resource[0], 0,
300 sizeof(struct p9100_regs), "p9100 regs"); 289 sizeof(struct p9100_regs), "p9100 regs");
290 if (!all->par.regs) {
291 kfree(all);
292 return -ENOMEM;
293 }
301 294
302 all->info.flags = FBINFO_DEFAULT; 295 all->info.flags = FBINFO_DEFAULT;
303 all->info.fbops = &p9100_ops; 296 all->info.fbops = &p9100_ops;
304#ifdef CONFIG_SPARC32 297 all->info.screen_base = of_ioremap(&op->resource[2], 0,
305 all->info.screen_base = (char __iomem *) 298 all->par.fbsize, "p9100 ram");
306 prom_getintdefault(sdev->prom_node, "address", 0); 299 if (!all->info.screen_base) {
307#endif 300 of_iounmap(all->par.regs, sizeof(struct p9100_regs));
308 if (!all->info.screen_base) 301 kfree(all);
309 all->info.screen_base = sbus_ioremap(&sdev->resource[2], 0, 302 return -ENOMEM;
310 all->par.fbsize, "p9100 ram"); 303 }
311 all->info.par = &all->par; 304 all->info.par = &all->par;
312 305
313 p9100_blank(0, &all->info); 306 p9100_blank(0, &all->info);
314 307
315 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { 308 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
316 printk(KERN_ERR "p9100: Could not allocate color map.\n"); 309 of_iounmap(all->par.regs, sizeof(struct p9100_regs));
310 of_iounmap(all->info.screen_base, all->par.fbsize);
317 kfree(all); 311 kfree(all);
318 return; 312 return -ENOMEM;
319 } 313 }
320 314
321 p9100_init_fix(&all->info, linebytes); 315 p9100_init_fix(&all->info, linebytes, dp);
322 316
323 if (register_framebuffer(&all->info) < 0) { 317 err = register_framebuffer(&all->info);
324 printk(KERN_ERR "p9100: Could not register framebuffer.\n"); 318 if (err < 0) {
325 fb_dealloc_cmap(&all->info.cmap); 319 fb_dealloc_cmap(&all->info.cmap);
320 of_iounmap(all->par.regs, sizeof(struct p9100_regs));
321 of_iounmap(all->info.screen_base, all->par.fbsize);
326 kfree(all); 322 kfree(all);
327 return; 323 return err;
328 } 324 }
329 fb_set_cmap(&all->info.cmap, &all->info); 325 fb_set_cmap(&all->info.cmap, &all->info);
330 326
331 list_add(&all->list, &p9100_list); 327 dev_set_drvdata(&op->dev, all);
328
329 printk("%s: p9100 at %lx:%lx\n",
330 dp->full_name,
331 all->par.which_io, all->par.physbase);
332 332
333 printk("p9100: %s at %lx:%lx\n", 333 return 0;
334 sdev->prom_name,
335 (long) sdev->reg_addrs[0].which_io,
336 (long) sdev->reg_addrs[0].phys_addr);
337} 334}
338 335
339int __init p9100_init(void) 336static int __devinit p9100_probe(struct of_device *dev, const struct of_device_id *match)
340{ 337{
341 struct sbus_bus *sbus; 338 struct of_device *op = to_of_device(&dev->dev);
342 struct sbus_dev *sdev;
343 339
344 if (fb_get_options("p9100fb", NULL)) 340 return p9100_init_one(op);
345 return -ENODEV; 341}
346 342
347 for_all_sbusdev(sdev, sbus) { 343static int __devexit p9100_remove(struct of_device *dev)
348 if (!strcmp(sdev->prom_name, "p9100")) 344{
349 p9100_init_one(sdev); 345 struct all_info *all = dev_get_drvdata(&dev->dev);
350 } 346
347 unregister_framebuffer(&all->info);
348 fb_dealloc_cmap(&all->info.cmap);
349
350 of_iounmap(all->par.regs, sizeof(struct p9100_regs));
351 of_iounmap(all->info.screen_base, all->par.fbsize);
352
353 kfree(all);
354
355 dev_set_drvdata(&dev->dev, NULL);
351 356
352 return 0; 357 return 0;
353} 358}
354 359
355void __exit p9100_exit(void) 360static struct of_device_id p9100_match[] = {
356{ 361 {
357 struct list_head *pos, *tmp; 362 .name = "p9100",
363 },
364 {},
365};
366MODULE_DEVICE_TABLE(of, p9100_match);
358 367
359 list_for_each_safe(pos, tmp, &p9100_list) { 368static struct of_platform_driver p9100_driver = {
360 struct all_info *all = list_entry(pos, typeof(*all), list); 369 .name = "p9100",
370 .match_table = p9100_match,
371 .probe = p9100_probe,
372 .remove = __devexit_p(p9100_remove),
373};
361 374
362 unregister_framebuffer(&all->info); 375static int __init p9100_init(void)
363 fb_dealloc_cmap(&all->info.cmap); 376{
364 kfree(all); 377 if (fb_get_options("p9100fb", NULL))
365 } 378 return -ENODEV;
379
380 return of_register_driver(&p9100_driver, &of_bus_type);
366} 381}
367 382
368int __init 383static void __exit p9100_exit(void)
369p9100_setup(char *arg)
370{ 384{
371 /* No cmdline options yet... */ 385 of_unregister_driver(&p9100_driver);
372 return 0;
373} 386}
374 387
375module_init(p9100_init); 388module_init(p9100_init);
376
377#ifdef MODULE
378module_exit(p9100_exit); 389module_exit(p9100_exit);
379#endif
380 390
381MODULE_DESCRIPTION("framebuffer driver for P9100 chipsets"); 391MODULE_DESCRIPTION("framebuffer driver for P9100 chipsets");
382MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); 392MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
393MODULE_VERSION("2.0");
383MODULE_LICENSE("GPL"); 394MODULE_LICENSE("GPL");
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index 95b918229d9b..6990ab11cd06 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -1,6 +1,6 @@
1/* tcx.c: TCX frame buffer driver 1/* tcx.c: TCX frame buffer driver
2 * 2 *
3 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 3 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) 4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
5 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) 5 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
6 * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) 6 * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
@@ -19,8 +19,8 @@
19#include <linux/mm.h> 19#include <linux/mm.h>
20 20
21#include <asm/io.h> 21#include <asm/io.h>
22#include <asm/sbus.h> 22#include <asm/prom.h>
23#include <asm/oplib.h> 23#include <asm/of_device.h>
24#include <asm/fbio.h> 24#include <asm/fbio.h>
25 25
26#include "sbuslib.h" 26#include "sbuslib.h"
@@ -77,32 +77,32 @@ static struct fb_ops tcx_ops = {
77 77
78/* The contents are unknown */ 78/* The contents are unknown */
79struct tcx_tec { 79struct tcx_tec {
80 volatile u32 tec_matrix; 80 u32 tec_matrix;
81 volatile u32 tec_clip; 81 u32 tec_clip;
82 volatile u32 tec_vdc; 82 u32 tec_vdc;
83}; 83};
84 84
85struct tcx_thc { 85struct tcx_thc {
86 volatile u32 thc_rev; 86 u32 thc_rev;
87 u32 thc_pad0[511]; 87 u32 thc_pad0[511];
88 volatile u32 thc_hs; /* hsync timing */ 88 u32 thc_hs; /* hsync timing */
89 volatile u32 thc_hsdvs; 89 u32 thc_hsdvs;
90 volatile u32 thc_hd; 90 u32 thc_hd;
91 volatile u32 thc_vs; /* vsync timing */ 91 u32 thc_vs; /* vsync timing */
92 volatile u32 thc_vd; 92 u32 thc_vd;
93 volatile u32 thc_refresh; 93 u32 thc_refresh;
94 volatile u32 thc_misc; 94 u32 thc_misc;
95 u32 thc_pad1[56]; 95 u32 thc_pad1[56];
96 volatile u32 thc_cursxy; /* cursor x,y position (16 bits each) */ 96 u32 thc_cursxy; /* cursor x,y position (16 bits each) */
97 volatile u32 thc_cursmask[32]; /* cursor mask bits */ 97 u32 thc_cursmask[32]; /* cursor mask bits */
98 volatile u32 thc_cursbits[32]; /* what to show where mask enabled */ 98 u32 thc_cursbits[32]; /* what to show where mask enabled */
99}; 99};
100 100
101struct bt_regs { 101struct bt_regs {
102 volatile u32 addr; 102 u32 addr;
103 volatile u32 color_map; 103 u32 color_map;
104 volatile u32 control; 104 u32 control;
105 volatile u32 cursor; 105 u32 cursor;
106}; 106};
107 107
108#define TCX_MMAP_ENTRIES 14 108#define TCX_MMAP_ENTRIES 14
@@ -112,24 +112,23 @@ struct tcx_par {
112 struct bt_regs __iomem *bt; 112 struct bt_regs __iomem *bt;
113 struct tcx_thc __iomem *thc; 113 struct tcx_thc __iomem *thc;
114 struct tcx_tec __iomem *tec; 114 struct tcx_tec __iomem *tec;
115 volatile u32 __iomem *cplane; 115 u32 __iomem *cplane;
116 116
117 u32 flags; 117 u32 flags;
118#define TCX_FLAG_BLANKED 0x00000001 118#define TCX_FLAG_BLANKED 0x00000001
119 119
120 unsigned long physbase; 120 unsigned long physbase;
121 unsigned long which_io;
121 unsigned long fbsize; 122 unsigned long fbsize;
122 123
123 struct sbus_mmap_map mmap_map[TCX_MMAP_ENTRIES]; 124 struct sbus_mmap_map mmap_map[TCX_MMAP_ENTRIES];
124 int lowdepth; 125 int lowdepth;
125
126 struct sbus_dev *sdev;
127}; 126};
128 127
129/* Reset control plane so that WID is 8-bit plane. */ 128/* Reset control plane so that WID is 8-bit plane. */
130static void __tcx_set_control_plane (struct tcx_par *par) 129static void __tcx_set_control_plane (struct tcx_par *par)
131{ 130{
132 volatile u32 __iomem *p, *pend; 131 u32 __iomem *p, *pend;
133 132
134 if (par->lowdepth) 133 if (par->lowdepth)
135 return; 134 return;
@@ -307,8 +306,7 @@ static int tcx_mmap(struct fb_info *info, struct vm_area_struct *vma)
307 306
308 return sbusfb_mmap_helper(par->mmap_map, 307 return sbusfb_mmap_helper(par->mmap_map,
309 par->physbase, par->fbsize, 308 par->physbase, par->fbsize,
310 par->sdev->reg_addrs[0].which_io, 309 par->which_io, vma);
311 vma);
312} 310}
313 311
314static int tcx_ioctl(struct fb_info *info, unsigned int cmd, 312static int tcx_ioctl(struct fb_info *info, unsigned int cmd,
@@ -350,48 +348,71 @@ tcx_init_fix(struct fb_info *info, int linebytes)
350struct all_info { 348struct all_info {
351 struct fb_info info; 349 struct fb_info info;
352 struct tcx_par par; 350 struct tcx_par par;
353 struct list_head list;
354}; 351};
355static LIST_HEAD(tcx_list);
356 352
357static void tcx_init_one(struct sbus_dev *sdev) 353static void tcx_unmap_regs(struct all_info *all)
358{ 354{
359 struct all_info *all; 355 if (all->par.tec)
360 int linebytes, i; 356 of_iounmap(all->par.tec, sizeof(struct tcx_tec));
357 if (all->par.thc)
358 of_iounmap(all->par.thc, sizeof(struct tcx_thc));
359 if (all->par.bt)
360 of_iounmap(all->par.bt, sizeof(struct bt_regs));
361 if (all->par.cplane)
362 of_iounmap(all->par.cplane, all->par.fbsize * sizeof(u32));
363 if (all->info.screen_base)
364 of_iounmap(all->info.screen_base, all->par.fbsize);
365}
361 366
362 all = kmalloc(sizeof(*all), GFP_KERNEL); 367static int __devinit tcx_init_one(struct of_device *op)
363 if (!all) { 368{
364 printk(KERN_ERR "tcx: Cannot allocate memory.\n"); 369 struct device_node *dp = op->node;
365 return; 370 struct all_info *all;
366 } 371 int linebytes, i, err;
367 memset(all, 0, sizeof(*all));
368 372
369 INIT_LIST_HEAD(&all->list); 373 all = kzalloc(sizeof(*all), GFP_KERNEL);
374 if (!all)
375 return -ENOMEM;
370 376
371 spin_lock_init(&all->par.lock); 377 spin_lock_init(&all->par.lock);
372 all->par.sdev = sdev;
373 378
374 all->par.lowdepth = prom_getbool(sdev->prom_node, "tcx-8-bit"); 379 all->par.lowdepth =
380 (of_find_property(dp, "tcx-8-bit", NULL) != NULL);
375 381
376 sbusfb_fill_var(&all->info.var, sdev->prom_node, 8); 382 sbusfb_fill_var(&all->info.var, dp->node, 8);
377 all->info.var.red.length = 8; 383 all->info.var.red.length = 8;
378 all->info.var.green.length = 8; 384 all->info.var.green.length = 8;
379 all->info.var.blue.length = 8; 385 all->info.var.blue.length = 8;
380 386
381 linebytes = prom_getintdefault(sdev->prom_node, "linebytes", 387 linebytes = of_getintprop_default(dp, "linebytes",
382 all->info.var.xres); 388 all->info.var.xres);
383 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); 389 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
384 390
385 all->par.tec = sbus_ioremap(&sdev->resource[7], 0, 391 all->par.tec = of_ioremap(&op->resource[7], 0,
386 sizeof(struct tcx_tec), "tcx tec"); 392 sizeof(struct tcx_tec), "tcx tec");
387 all->par.thc = sbus_ioremap(&sdev->resource[9], 0, 393 all->par.thc = of_ioremap(&op->resource[9], 0,
388 sizeof(struct tcx_thc), "tcx thc"); 394 sizeof(struct tcx_thc), "tcx thc");
389 all->par.bt = sbus_ioremap(&sdev->resource[8], 0, 395 all->par.bt = of_ioremap(&op->resource[8], 0,
390 sizeof(struct bt_regs), "tcx dac"); 396 sizeof(struct bt_regs), "tcx dac");
397 all->info.screen_base = of_ioremap(&op->resource[0], 0,
398 all->par.fbsize, "tcx ram");
399 if (!all->par.tec || !all->par.thc ||
400 !all->par.bt || !all->info.screen_base) {
401 tcx_unmap_regs(all);
402 kfree(all);
403 return -ENOMEM;
404 }
405
391 memcpy(&all->par.mmap_map, &__tcx_mmap_map, sizeof(all->par.mmap_map)); 406 memcpy(&all->par.mmap_map, &__tcx_mmap_map, sizeof(all->par.mmap_map));
392 if (!all->par.lowdepth) { 407 if (!all->par.lowdepth) {
393 all->par.cplane = sbus_ioremap(&sdev->resource[4], 0, 408 all->par.cplane = of_ioremap(&op->resource[4], 0,
394 all->par.fbsize * sizeof(u32), "tcx cplane"); 409 all->par.fbsize * sizeof(u32),
410 "tcx cplane");
411 if (!all->par.cplane) {
412 tcx_unmap_regs(all);
413 kfree(all);
414 return -ENOMEM;
415 }
395 } else { 416 } else {
396 all->par.mmap_map[1].size = SBUS_MMAP_EMPTY; 417 all->par.mmap_map[1].size = SBUS_MMAP_EMPTY;
397 all->par.mmap_map[4].size = SBUS_MMAP_EMPTY; 418 all->par.mmap_map[4].size = SBUS_MMAP_EMPTY;
@@ -400,6 +421,8 @@ static void tcx_init_one(struct sbus_dev *sdev)
400 } 421 }
401 422
402 all->par.physbase = 0; 423 all->par.physbase = 0;
424 all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
425
403 for (i = 0; i < TCX_MMAP_ENTRIES; i++) { 426 for (i = 0; i < TCX_MMAP_ENTRIES; i++) {
404 int j; 427 int j;
405 428
@@ -416,18 +439,11 @@ static void tcx_init_one(struct sbus_dev *sdev)
416 j = i; 439 j = i;
417 break; 440 break;
418 }; 441 };
419 all->par.mmap_map[i].poff = sdev->reg_addrs[j].phys_addr; 442 all->par.mmap_map[i].poff = op->resource[j].start;
420 } 443 }
421 444
422 all->info.flags = FBINFO_DEFAULT; 445 all->info.flags = FBINFO_DEFAULT;
423 all->info.fbops = &tcx_ops; 446 all->info.fbops = &tcx_ops;
424#ifdef CONFIG_SPARC32
425 all->info.screen_base = (char __iomem *)
426 prom_getintdefault(sdev->prom_node, "address", 0);
427#endif
428 if (!all->info.screen_base)
429 all->info.screen_base = sbus_ioremap(&sdev->resource[0], 0,
430 all->par.fbsize, "tcx ram");
431 all->info.par = &all->par; 447 all->info.par = &all->par;
432 448
433 /* Initialize brooktree DAC. */ 449 /* Initialize brooktree DAC. */
@@ -445,72 +461,88 @@ static void tcx_init_one(struct sbus_dev *sdev)
445 tcx_blank(FB_BLANK_UNBLANK, &all->info); 461 tcx_blank(FB_BLANK_UNBLANK, &all->info);
446 462
447 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { 463 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
448 printk(KERN_ERR "tcx: Could not allocate color map.\n"); 464 tcx_unmap_regs(all);
449 kfree(all); 465 kfree(all);
450 return; 466 return -ENOMEM;
451 } 467 }
452 468
453 fb_set_cmap(&all->info.cmap, &all->info); 469 fb_set_cmap(&all->info.cmap, &all->info);
454 tcx_init_fix(&all->info, linebytes); 470 tcx_init_fix(&all->info, linebytes);
455 471
456 if (register_framebuffer(&all->info) < 0) { 472 err = register_framebuffer(&all->info);
457 printk(KERN_ERR "tcx: Could not register framebuffer.\n"); 473 if (err < 0) {
458 fb_dealloc_cmap(&all->info.cmap); 474 fb_dealloc_cmap(&all->info.cmap);
475 tcx_unmap_regs(all);
459 kfree(all); 476 kfree(all);
460 return; 477 return err;
461 } 478 }
462 479
463 list_add(&all->list, &tcx_list); 480 dev_set_drvdata(&op->dev, all);
464 481
465 printk("tcx: %s at %lx:%lx, %s\n", 482 printk("%s: TCX at %lx:%lx, %s\n",
466 sdev->prom_name, 483 dp->full_name,
467 (long) sdev->reg_addrs[0].which_io, 484 all->par.which_io,
468 (long) sdev->reg_addrs[0].phys_addr, 485 op->resource[0].start,
469 all->par.lowdepth ? "8-bit only" : "24-bit depth"); 486 all->par.lowdepth ? "8-bit only" : "24-bit depth");
487
488 return 0;
470} 489}
471 490
472int __init tcx_init(void) 491static int __devinit tcx_probe(struct of_device *dev, const struct of_device_id *match)
473{ 492{
474 struct sbus_bus *sbus; 493 struct of_device *op = to_of_device(&dev->dev);
475 struct sbus_dev *sdev;
476 494
477 if (fb_get_options("tcxfb", NULL)) 495 return tcx_init_one(op);
478 return -ENODEV; 496}
479 497
480 for_all_sbusdev(sdev, sbus) { 498static int __devexit tcx_remove(struct of_device *dev)
481 if (!strcmp(sdev->prom_name, "SUNW,tcx")) 499{
482 tcx_init_one(sdev); 500 struct all_info *all = dev_get_drvdata(&dev->dev);
483 } 501
502 unregister_framebuffer(&all->info);
503 fb_dealloc_cmap(&all->info.cmap);
504
505 tcx_unmap_regs(all);
506
507 kfree(all);
508
509 dev_set_drvdata(&dev->dev, NULL);
484 510
485 return 0; 511 return 0;
486} 512}
487 513
488void __exit tcx_exit(void) 514static struct of_device_id tcx_match[] = {
489{ 515 {
490 struct list_head *pos, *tmp; 516 .name = "SUNW,tcx",
517 },
518 {},
519};
520MODULE_DEVICE_TABLE(of, tcx_match);
491 521
492 list_for_each_safe(pos, tmp, &tcx_list) { 522static struct of_platform_driver tcx_driver = {
493 struct all_info *all = list_entry(pos, typeof(*all), list); 523 .name = "tcx",
524 .match_table = tcx_match,
525 .probe = tcx_probe,
526 .remove = __devexit_p(tcx_remove),
527};
494 528
495 unregister_framebuffer(&all->info); 529int __init tcx_init(void)
496 fb_dealloc_cmap(&all->info.cmap); 530{
497 kfree(all); 531 if (fb_get_options("tcxfb", NULL))
498 } 532 return -ENODEV;
533
534 return of_register_driver(&tcx_driver, &of_bus_type);
499} 535}
500 536
501int __init 537void __exit tcx_exit(void)
502tcx_setup(char *arg)
503{ 538{
504 /* No cmdline options yet... */ 539 of_unregister_driver(&tcx_driver);
505 return 0;
506} 540}
507 541
508module_init(tcx_init); 542module_init(tcx_init);
509
510#ifdef MODULE
511module_exit(tcx_exit); 543module_exit(tcx_exit);
512#endif
513 544
514MODULE_DESCRIPTION("framebuffer driver for TCX chipsets"); 545MODULE_DESCRIPTION("framebuffer driver for TCX chipsets");
515MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); 546MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
547MODULE_VERSION("2.0");
516MODULE_LICENSE("GPL"); 548MODULE_LICENSE("GPL");