aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/p9100.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/p9100.c')
-rw-r--r--drivers/video/p9100.c251
1 files changed, 131 insertions, 120 deletions
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index 0d195750535..56ac51d6a7f 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");