make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / drivers / video / bwtwofb.c
1 /* $Id: bwtwofb.c,v 1.1.1.1 2005/04/11 02:50:41 jack Exp $
2  * bwtwofb.c: BWtwo frame buffer driver
3  *
4  * Copyright (C) 1998 Jakub Jelinek   (jj@ultra.linux.cz)
5  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
6  * Copyright (C) 1997 Eddie C. Dost   (ecd@skynet.be)
7  * Copyright (C) 1998 Pavel Machek    (pavel@ucw.cz)
8  */
9
10 #include <linux/config.h>
11 #include <linux/module.h>
12 #include <linux/sched.h>
13 #include <linux/kernel.h>
14 #include <linux/errno.h>
15 #include <linux/string.h>
16 #include <linux/mm.h>
17 #include <linux/tty.h>
18 #include <linux/slab.h>
19 #include <linux/vmalloc.h>
20 #include <linux/delay.h>
21 #include <linux/interrupt.h>
22 #include <linux/fb.h>
23 #include <linux/init.h>
24 #include <linux/selection.h>
25
26 #include <video/sbusfb.h>
27 #include <asm/io.h>
28 #if !defined(__sparc_v9__) && !defined(__mc68000__)
29 #include <asm/sun4paddr.h>
30 #endif
31
32 #include <video/fbcon-mfb.h>
33
34 /* OBio addresses for the bwtwo registers */
35 #define BWTWO_REGISTER_OFFSET 0x400000
36
37 struct bw2_regs {
38         struct bt_regs          bt;
39         volatile u8             control;
40         volatile u8             status;
41         volatile u8             cursor_start;
42         volatile u8             cursor_end;
43         volatile u8             h_blank_start;
44         volatile u8             h_blank_end;
45         volatile u8             h_sync_start;
46         volatile u8             h_sync_end;
47         volatile u8             comp_sync_end;
48         volatile u8             v_blank_start_high;
49         volatile u8             v_blank_start_low;
50         volatile u8             v_blank_end;
51         volatile u8             v_sync_start;
52         volatile u8             v_sync_end;
53         volatile u8             xfer_holdoff_start;
54         volatile u8             xfer_holdoff_end;
55 };
56
57 /* Status Register Constants */
58 #define BWTWO_SR_RES_MASK       0x70
59 #define BWTWO_SR_1600_1280      0x50
60 #define BWTWO_SR_1152_900_76_A  0x40
61 #define BWTWO_SR_1152_900_76_B  0x60
62 #define BWTWO_SR_ID_MASK        0x0f
63 #define BWTWO_SR_ID_MONO        0x02
64 #define BWTWO_SR_ID_MONO_ECL    0x03
65 #define BWTWO_SR_ID_MSYNC       0x04
66 #define BWTWO_SR_ID_NOCONN      0x0a
67
68 /* Control Register Constants */
69 #define BWTWO_CTL_ENABLE_INTS   0x80
70 #define BWTWO_CTL_ENABLE_VIDEO  0x40
71 #define BWTWO_CTL_ENABLE_TIMING 0x20
72 #define BWTWO_CTL_ENABLE_CURCMP 0x10
73 #define BWTWO_CTL_XTAL_MASK     0x0C
74 #define BWTWO_CTL_DIVISOR_MASK  0x03
75
76 /* Status Register Constants */
77 #define BWTWO_STAT_PENDING_INT  0x80
78 #define BWTWO_STAT_MSENSE_MASK  0x70
79 #define BWTWO_STAT_ID_MASK      0x0f
80
81 static struct sbus_mmap_map bw2_mmap_map[] = {
82         { 0,                    0,                      SBUS_MMAP_FBSIZE(1) },
83         { 0,                    0,                      0                   }
84 };
85
86 static void bw2_blank (struct fb_info_sbusfb *fb)
87 {
88         unsigned long flags;
89         u8 tmp;
90
91         spin_lock_irqsave(&fb->lock, flags);
92         tmp = sbus_readb(&fb->s.bw2.regs->control);
93         tmp &= ~BWTWO_CTL_ENABLE_VIDEO;
94         sbus_writeb(tmp, &fb->s.bw2.regs->control);
95         spin_unlock_irqrestore(&fb->lock, flags);
96 }
97
98 static void bw2_unblank (struct fb_info_sbusfb *fb)
99 {
100         unsigned long flags;
101         u8 tmp;
102
103         spin_lock_irqsave(&fb->lock, flags);
104         tmp = sbus_readb(&fb->s.bw2.regs->control);
105         tmp |= BWTWO_CTL_ENABLE_VIDEO;
106         sbus_writeb(tmp, &fb->s.bw2.regs->control);
107         spin_unlock_irqrestore(&fb->lock, flags);
108 }
109
110 static void bw2_margins (struct fb_info_sbusfb *fb, struct display *p,
111                          int x_margin, int y_margin)
112 {
113         p->screen_base += (y_margin - fb->y_margin) *
114                 p->line_length + ((x_margin - fb->x_margin) >> 3);
115 }
116
117 static u8 bw2regs_1600[] __initdata = {
118         0x14, 0x8b,     0x15, 0x28,     0x16, 0x03,     0x17, 0x13,
119         0x18, 0x7b,     0x19, 0x05,     0x1a, 0x34,     0x1b, 0x2e,
120         0x1c, 0x00,     0x1d, 0x0a,     0x1e, 0xff,     0x1f, 0x01,
121         0x10, 0x21,     0
122 };
123
124 static u8 bw2regs_ecl[] __initdata = {
125         0x14, 0x65,     0x15, 0x1e,     0x16, 0x04,     0x17, 0x0c,
126         0x18, 0x5e,     0x19, 0x03,     0x1a, 0xa7,     0x1b, 0x23,
127         0x1c, 0x00,     0x1d, 0x08,     0x1e, 0xff,     0x1f, 0x01,
128         0x10, 0x20,     0
129 };
130
131 static u8 bw2regs_analog[] __initdata = {
132         0x14, 0xbb,     0x15, 0x2b,     0x16, 0x03,     0x17, 0x13,
133         0x18, 0xb0,     0x19, 0x03,     0x1a, 0xa6,     0x1b, 0x22,
134         0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
135         0x10, 0x20,     0
136 };
137
138 static u8 bw2regs_76hz[] __initdata = {
139         0x14, 0xb7,     0x15, 0x27,     0x16, 0x03,     0x17, 0x0f,
140         0x18, 0xae,     0x19, 0x03,     0x1a, 0xae,     0x1b, 0x2a,
141         0x1c, 0x01,     0x1d, 0x09,     0x1e, 0xff,     0x1f, 0x01,
142         0x10, 0x24,     0
143 };
144
145 static u8 bw2regs_66hz[] __initdata = {
146         0x14, 0xbb,     0x15, 0x2b,     0x16, 0x04,     0x17, 0x14,
147         0x18, 0xae,     0x19, 0x03,     0x1a, 0xa8,     0x1b, 0x24,
148         0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
149         0x10, 0x20,     0
150 };
151
152 static char idstring[60] __initdata = { 0 };
153
154 char __init *bwtwofb_init(struct fb_info_sbusfb *fb)
155 {
156         struct fb_fix_screeninfo *fix = &fb->fix;
157         struct display *disp = &fb->disp;
158         struct fbtype *type = &fb->type;
159 #ifdef CONFIG_SUN4
160         unsigned long phys = sun4_bwtwo_physaddr;
161         struct resource res;
162 #else
163         unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
164 #endif
165         struct resource *resp;
166         unsigned int vaddr;
167
168 #ifndef FBCON_HAS_MFB
169         return NULL;
170 #endif
171
172 #ifdef CONFIG_SUN4
173         res.start = phys;
174         res.end = res.start + BWTWO_REGISTER_OFFSET + sizeof(struct bw2_regs) - 1;
175         res.flags = IORESOURCE_IO | (fb->iospace & 0xff);
176         resp = &res;
177 #else
178         resp = &fb->sbdp->resource[0];
179 #endif
180         if (!fb->s.bw2.regs) {
181                 fb->s.bw2.regs = (struct bw2_regs *)
182                         sbus_ioremap(resp, BWTWO_REGISTER_OFFSET,
183                                      sizeof(struct bw2_regs), "bw2 regs");
184                 if ((!ARCH_SUN4) && (!prom_getbool(fb->prom_node, "width"))) {
185                         /* Ugh, broken PROM didn't initialize us.
186                          * Let's deal with this ourselves.
187                          */
188                         u8 status, mon;
189                         u8 *p;
190                         int sizechange = 0;
191
192                         status = sbus_readb(&fb->s.bw2.regs->status);
193                         mon = status & BWTWO_SR_RES_MASK;
194                         switch (status & BWTWO_SR_ID_MASK) {
195                                 case BWTWO_SR_ID_MONO_ECL:
196                                         if (mon == BWTWO_SR_1600_1280) {
197                                                 p = bw2regs_1600;
198                                                 fb->type.fb_width = 1600;
199                                                 fb->type.fb_height = 1280;
200                                                 sizechange = 1;
201                                         } else
202                                                 p = bw2regs_ecl;
203                                         break;
204                                 case BWTWO_SR_ID_MONO:
205                                         p = bw2regs_analog;
206                                         break;
207                                 case BWTWO_SR_ID_MSYNC:
208                                         if (mon == BWTWO_SR_1152_900_76_A ||
209                                             mon == BWTWO_SR_1152_900_76_B)
210                                                 p = bw2regs_76hz;
211                                         else
212                                                 p = bw2regs_66hz;
213                                         break;
214                                 case BWTWO_SR_ID_NOCONN:
215                                         return NULL;
216                                 default:
217 #ifndef CONFIG_FB_SUN3
218                                         prom_printf("bw2: can't handle SR %02x\n",
219                                                     status);
220                                         prom_halt();
221 #endif                                  
222                                         return NULL; /* fool gcc. */
223                         }
224                         for ( ; *p; p += 2) {
225                                 u8 *regp = &((u8 *)fb->s.bw2.regs)[p[0]];
226                                 sbus_writeb(p[1], regp);
227                         }
228                 }
229         }
230
231         strcpy(fb->info.modename, "BWtwo");
232         strcpy(fix->id, "BWtwo");
233         fix->line_length = fb->var.xres_virtual >> 3;
234         fix->accel = FB_ACCEL_SUN_BWTWO;
235         
236         disp->scrollmode = SCROLL_YREDRAW;
237         disp->inverse = 1;
238         if (!disp->screen_base) {
239                 disp->screen_base = (char *)
240                         sbus_ioremap(resp, 0, type->fb_size, "bw2 ram");
241         }
242         disp->screen_base += fix->line_length * fb->y_margin + (fb->x_margin >> 3);
243         fb->dispsw = fbcon_mfb;
244         fix->visual = FB_VISUAL_MONO01;
245
246 #ifndef CONFIG_SUN4
247         fb->blank = bw2_blank;
248         fb->unblank = bw2_unblank;
249
250         prom_getproperty(fb->sbdp->prom_node, "address",
251                          (char *)&vaddr, sizeof(vaddr));
252         fb->physbase = __get_phys((unsigned long)vaddr);
253
254 #endif
255         fb->margins = bw2_margins;
256         fb->mmap_map = bw2_mmap_map;
257
258 #ifdef __sparc_v9__
259         sprintf(idstring, "bwtwo at %016lx", phys);
260 #else   
261         sprintf(idstring, "bwtwo at %x.%08lx", fb->iospace, phys);
262 #endif
263         
264         return idstring;
265 }
266
267 MODULE_LICENSE("GPL");