File: /usr/src/linux/drivers/video/p9100fb.c

1     /* $id: p9100fb.c,v 1.4 1999/08/18 10:55:01 shadow Exp $
2      * p9100fb.c: P9100 frame buffer driver
3      *
4      * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
5      */
6     
7     #include <linux/module.h>
8     #include <linux/sched.h>
9     #include <linux/kernel.h>
10     #include <linux/errno.h>
11     #include <linux/string.h>
12     #include <linux/mm.h>
13     #include <linux/tty.h>
14     #include <linux/slab.h>
15     #include <linux/vmalloc.h>
16     #include <linux/delay.h>
17     #include <linux/interrupt.h>
18     #include <linux/fb.h>
19     #include <linux/init.h>
20     #include <linux/selection.h>
21     
22     #include <video/sbusfb.h>
23     #include <asm/io.h>
24     
25     #include <video/fbcon-cfb8.h>
26     
27     #include "p9100.h"
28     
29     static struct sbus_mmap_map p9100_mmap_map[] = {
30     #if 0 /* For now, play we're a dumb color fb */
31       { P9100_CTL_OFF, 0x38000000, 0x2000 },
32       { P9100_CMD_OFF, 0x38002000, 0x2000 },
33       { P9100_FB_OFF, 0x38800000, 0x200000 },
34       { CG3_MMAP_OFFSET, 0x38800000, SBUS_MMAP_FBSIZE(1) },
35     #else
36       { CG3_MMAP_OFFSET, 0x0, SBUS_MMAP_FBSIZE(1) },
37     #endif
38       { 0, 0, 0 }
39     };
40     
41     #define _READCTL(member, out) \
42     { \
43       struct p9100_ctrl *actual; \
44       actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \
45       out = sbus_readl(&actual-> ## member ); \
46     }
47     
48     #define READCTL(member, out) \
49     { \
50       struct p9100_ctrl *enab, *actual; \
51       actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \
52       enab = (struct p9100_ctrl *)fb->s.p9100.fbmem; \
53       out = sbus_readl(&enab-> ## member ); \
54       out = sbus_readl(&actual-> ## member ); \
55     }
56     
57     #define WRITECTL(member, val) \
58     { \
59       u32 __writetmp; \
60       struct p9100_ctrl *enab, *actual; \
61       actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \
62       enab = (struct p9100_ctrl *)fb->s.p9100.fbmem; \
63       __writetmp = sbus_readl(&enab-> ## member ); \
64       sbus_writel(val, &actual-> ## member ); \
65     }
66     
67     static void p9100_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
68     {
69     	unsigned long flags;
70     	u32 tmp;
71     	int i;
72     
73     	spin_lock_irqsave(&fb->lock, flags);
74     
75     	_READCTL(pwrup_cfg, tmp);
76     	WRITECTL(ramdac_cmap_wridx, (index << 16));
77     
78     	for (i = index; count--; i++){
79     		_READCTL(pwrup_cfg, tmp);
80     		WRITECTL(ramdac_palette_data, (fb->color_map CM(i,0) << 16));
81     		_READCTL(pwrup_cfg, tmp);
82     		WRITECTL(ramdac_palette_data, (fb->color_map CM(i,1) << 16));
83     		_READCTL(pwrup_cfg, tmp);
84     		WRITECTL(ramdac_palette_data, (fb->color_map CM(i,2) << 16));
85     	}
86     
87     	spin_unlock_irqrestore(&fb->lock, flags);
88     }
89     
90     static void p9100_blank (struct fb_info_sbusfb *fb)
91     {
92     	unsigned long flags;
93     	u32 val;
94     
95     	spin_lock_irqsave(&fb->lock, flags);
96     	READCTL(vid_screenpaint_timectl1, val);
97     	val &= ~ SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
98     	WRITECTL(vid_screenpaint_timectl1, val);
99     	spin_unlock_irqrestore(&fb->lock, flags);
100     }
101     
102     static void p9100_unblank (struct fb_info_sbusfb *fb)
103     {
104     	unsigned long flags;
105     	u32 val;
106     
107     	spin_lock_irqsave(&fb->lock, flags);
108     	READCTL(vid_screenpaint_timectl1, val);
109     	val |= SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
110     	WRITECTL(vid_screenpaint_timectl1, val);
111     	spin_unlock_irqrestore(&fb->lock, flags);
112     }
113     
114     static void p9100_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
115     {
116       p->screen_base += (y_margin - fb->y_margin) * p->line_length + 
117         (x_margin - fb->x_margin);
118     }
119     
120     static char idstring[60] __initdata = { 0 };
121     
122     char * __init p9100fb_init(struct fb_info_sbusfb *fb)
123     {
124     	struct fb_fix_screeninfo *fix = &fb->fix;
125     	struct display *disp = &fb->disp;
126     	struct fbtype *type = &fb->type;
127     	struct sbus_dev *sdev = fb->sbdp;
128     	unsigned long phys = sdev->reg_addrs[2].phys_addr;
129     	int tmp;
130     
131     #ifndef FBCON_HAS_CFB8
132     	return NULL;
133     #endif
134     
135     	/* Control regs: fb->sbdp->reg_addrs[0].phys_addr 
136     	 * Command regs: fb->sbdp->reg_addrs[1].phys_addr 
137     	 * Frame buffer: fb->sbdp->reg_addrs[2].phys_addr 
138              */
139     
140     	if (!fb->s.p9100.ctrl) {
141     		fb->s.p9100.ctrl = (struct p9100_ctrl *)
142     			sbus_ioremap(&sdev->resource[0], 0,
143     				     sdev->reg_addrs[0].reg_size, "p9100 ctrl");
144     	}
145     
146     	strcpy(fb->info.modename, "p9100");
147     	strcpy(fix->id, "p9100");
148     	fix->accel = FB_ACCEL_SUN_CGTHREE;
149     	fix->line_length = fb->var.xres_virtual;
150     
151     	disp->scrollmode = SCROLL_YREDRAW;
152     	if (!disp->screen_base)
153     		disp->screen_base = (char *)
154     			sbus_ioremap(&sdev->resource[2], 0,
155     				     type->fb_size, "p9100 ram");
156     	fb->s.p9100.fbmem = (volatile u32 *)disp->screen_base;
157     	disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
158     
159     	READCTL(sys_config, tmp);
160             switch ((tmp >> SYS_CONFIG_PIXELSIZE_SHIFT) & 7) {
161     	case 7: 
162     	  type->fb_depth = 24; 
163     	  break;
164     	case 5: 
165     	  type->fb_depth = 32;
166     	  break;
167     	case 3: 
168     	  type->fb_depth = 16; 
169     	  break;
170     	case 2: 
171     	  type->fb_depth = 8; 
172     	  break;
173     	default: 
174     	  printk("p9100: screen depth unknown: 0x%x", tmp);
175     	  return NULL;
176             }
177     
178     	fb->dispsw = fbcon_cfb8;
179     
180     	fb->margins = p9100_margins;
181     	fb->loadcmap = p9100_loadcmap;
182     	fb->blank = p9100_blank;
183     	fb->unblank = p9100_unblank;
184     	
185     	fb->physbase = phys;
186     	fb->mmap_map = p9100_mmap_map;
187     	
188     	sprintf(idstring, "%s at 0x%x", "p9100", 
189     		(unsigned int)disp->screen_base);
190     
191     	return idstring;
192     }
193     
194