~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/video/cgthreefb.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* $Id: cgthreefb.c,v 1.9 2000/03/19 04:20:44 anton Exp $
  2  * cgthreefb.c: CGthree frame buffer driver
  3  *
  4  * Copyright (C) 1996,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  */
  8 
  9 #include <linux/module.h>
 10 #include <linux/sched.h>
 11 #include <linux/kernel.h>
 12 #include <linux/errno.h>
 13 #include <linux/string.h>
 14 #include <linux/mm.h>
 15 #include <linux/tty.h>
 16 #include <linux/malloc.h>
 17 #include <linux/vmalloc.h>
 18 #include <linux/delay.h>
 19 #include <linux/interrupt.h>
 20 #include <linux/fb.h>
 21 #include <linux/init.h>
 22 #include <linux/selection.h>
 23 
 24 #include <video/sbusfb.h>
 25 #include <asm/io.h>
 26 
 27 #include <video/fbcon-cfb8.h>
 28 
 29 /* Control Register Constants */
 30 #define CG3_CR_ENABLE_INTS      0x80
 31 #define CG3_CR_ENABLE_VIDEO     0x40
 32 #define CG3_CR_ENABLE_TIMING    0x20
 33 #define CG3_CR_ENABLE_CURCMP    0x10
 34 #define CG3_CR_XTAL_MASK        0x0c
 35 #define CG3_CR_DIVISOR_MASK     0x03
 36 
 37 /* Status Register Constants */
 38 #define CG3_SR_PENDING_INT      0x80
 39 #define CG3_SR_RES_MASK         0x70
 40 #define CG3_SR_1152_900_76_A    0x40
 41 #define CG3_SR_1152_900_76_B    0x60
 42 #define CG3_SR_ID_MASK          0x0f
 43 #define CG3_SR_ID_COLOR         0x01
 44 #define CG3_SR_ID_MONO          0x02
 45 #define CG3_SR_ID_MONO_ECL      0x03
 46 
 47 enum cg3_type {
 48         CG3_AT_66HZ = 0,
 49         CG3_AT_76HZ,
 50         CG3_RDI
 51 };
 52 
 53 struct cg3_regs {
 54         struct bt_regs  cmap;
 55         volatile u8     control;
 56         volatile u8     status;
 57         volatile u8     cursor_start;
 58         volatile u8     cursor_end;
 59         volatile u8     h_blank_start;
 60         volatile u8     h_blank_end;
 61         volatile u8     h_sync_start;
 62         volatile u8     h_sync_end;
 63         volatile u8     comp_sync_end;
 64         volatile u8     v_blank_start_high;
 65         volatile u8     v_blank_start_low;
 66         volatile u8     v_blank_end;
 67         volatile u8     v_sync_start;
 68         volatile u8     v_sync_end;
 69         volatile u8     xfer_holdoff_start;
 70         volatile u8     xfer_holdoff_end;
 71 };
 72 
 73 /* Offset of interesting structures in the OBIO space */
 74 #define CG3_REGS_OFFSET      0x400000UL
 75 #define CG3_RAM_OFFSET       0x800000UL
 76 
 77 static struct sbus_mmap_map cg3_mmap_map[] = {
 78         { CG3_MMAP_OFFSET,      CG3_RAM_OFFSET,         SBUS_MMAP_FBSIZE(1) },
 79         { 0,                    0,                      0                   }
 80 };
 81 
 82 /* The cg3 palette is loaded with 4 color values at each time  */
 83 /* so you end up with: (rgb)(r), (gb)(rg), (b)(rgb), and so on */
 84 
 85 #define D4M3(x) ((((x)>>2)<<1) + ((x)>>2))      /* (x/4)*3 */
 86 #define D4M4(x) ((x)&~0x3)                      /* (x/4)*4 */
 87 
 88 static void cg3_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
 89 {
 90         struct bt_regs *bt = &fb->s.cg3.regs->cmap;
 91         unsigned long flags;
 92         u32 *i;
 93         volatile u8 *regp;
 94         int steps;
 95                 
 96         spin_lock_irqsave(&fb->lock, flags);
 97 
 98         i = (((u32 *)fb->color_map) + D4M3(index));
 99         steps = D4M3(index+count-1) - D4M3(index)+3;
100                                 
101         regp = (volatile u8 *)&bt->addr;
102         sbus_writeb(D4M4(index), regp);
103         while (steps--) {
104                 u32 val = *i++;
105                 sbus_writel(val, &bt->color_map);
106         }
107 
108         spin_unlock_irqrestore(&fb->lock, flags);
109 }
110 
111 static void cg3_blank (struct fb_info_sbusfb *fb)
112 {
113         unsigned long flags;
114         u8 tmp;
115 
116         spin_lock_irqsave(&fb->lock, flags);
117         tmp = sbus_readb(&fb->s.cg3.regs->control);
118         tmp &= ~CG3_CR_ENABLE_VIDEO;
119         sbus_writeb(tmp, &fb->s.cg3.regs->control);
120         spin_unlock_irqrestore(&fb->lock, flags);
121 }
122 
123 static void cg3_unblank (struct fb_info_sbusfb *fb)
124 {
125         unsigned long flags;
126         u8 tmp;
127 
128         spin_lock_irqsave(&fb->lock, flags);
129         tmp = sbus_readb(&fb->s.cg3.regs->control);
130         tmp |= CG3_CR_ENABLE_VIDEO;
131         sbus_writeb(tmp, &fb->s.cg3.regs->control);
132         spin_unlock_irqrestore(&fb->lock, flags);
133 }
134 
135 static void cg3_margins (struct fb_info_sbusfb *fb, struct display *p,
136                          int x_margin, int y_margin)
137 {
138         p->screen_base += (y_margin - fb->y_margin) *
139                 p->line_length + (x_margin - fb->x_margin);
140 }
141 
142 static u8 cg3regvals_66hz[] __initdata = {      /* 1152 x 900, 66 Hz */
143         0x14, 0xbb,     0x15, 0x2b,     0x16, 0x04,     0x17, 0x14,
144         0x18, 0xae,     0x19, 0x03,     0x1a, 0xa8,     0x1b, 0x24,
145         0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
146         0x10, 0x20,     0
147 };
148 
149 static u8 cg3regvals_76hz[] __initdata = {      /* 1152 x 900, 76 Hz */
150         0x14, 0xb7,     0x15, 0x27,     0x16, 0x03,     0x17, 0x0f,
151         0x18, 0xae,     0x19, 0x03,     0x1a, 0xae,     0x1b, 0x2a,
152         0x1c, 0x01,     0x1d, 0x09,     0x1e, 0xff,     0x1f, 0x01,
153         0x10, 0x24,     0
154 };
155 
156 static u8 cg3regvals_rdi[] __initdata = {       /* 640 x 480, cgRDI */
157         0x14, 0x70,     0x15, 0x20,     0x16, 0x08,     0x17, 0x10,
158         0x18, 0x06,     0x19, 0x02,     0x1a, 0x31,     0x1b, 0x51,
159         0x1c, 0x06,     0x1d, 0x0c,     0x1e, 0xff,     0x1f, 0x01,
160         0x10, 0x22,     0
161 };
162 
163 static u8 *cg3_regvals[] __initdata = {
164         cg3regvals_66hz, cg3regvals_76hz, cg3regvals_rdi
165 };
166 
167 static u_char cg3_dacvals[] __initdata = {
168         4, 0xff,        5, 0x00,        6, 0x70,        7, 0x00,        0
169 };
170 
171 static char idstring[60] __initdata = { 0 };
172 
173 char __init *cgthreefb_init(struct fb_info_sbusfb *fb)
174 {
175         struct fb_fix_screeninfo *fix = &fb->fix;
176         struct display *disp = &fb->disp;
177         struct fbtype *type = &fb->type;
178         struct sbus_dev *sdev = fb->sbdp;
179         unsigned long phys = sdev->reg_addrs[0].phys_addr;
180         int cgRDI = strstr(fb->sbdp->prom_name, "cgRDI") != NULL;
181 
182 #ifndef FBCON_HAS_CFB8
183         return NULL;
184 #endif
185 
186         if (!fb->s.cg3.regs) {
187                 fb->s.cg3.regs = (struct cg3_regs *)
188                         sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET,
189                                      sizeof(struct cg3_regs), "cg3 regs");
190                 if (cgRDI) {
191                         char buffer[40];
192                         char *p;
193                         int ww, hh;
194                 
195                         *buffer = 0;
196                         prom_getstring (fb->prom_node, "params", buffer, sizeof(buffer));
197                         if (*buffer) {
198                                 ww = simple_strtoul (buffer, &p, 10);
199                                 if (ww && *p == 'x') {
200                                         hh = simple_strtoul (p + 1, &p, 10);
201                                         if (hh && *p == '-') {
202                                                 if (type->fb_width != ww || type->fb_height != hh) {
203                                                         type->fb_width = ww;
204                                                         type->fb_height = hh;
205                                                         return SBUSFBINIT_SIZECHANGE;
206                                                 }
207                                         }
208                                 }
209                         }
210                 }
211         }
212 
213         strcpy(fb->info.modename, "CGthree");
214         strcpy(fix->id, "CGthree");
215         fix->line_length = fb->var.xres_virtual;
216         fix->accel = FB_ACCEL_SUN_CGTHREE;
217         
218         disp->scrollmode = SCROLL_YREDRAW;
219         if (!disp->screen_base) {
220                 disp->screen_base = (char *)
221                         sbus_ioremap(&sdev->resource[0], CG3_RAM_OFFSET,
222                                      type->fb_size, "cg3 ram");
223         }
224         disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
225         fb->dispsw = fbcon_cfb8;
226 
227         fb->margins = cg3_margins;
228         fb->loadcmap = cg3_loadcmap;
229         fb->blank = cg3_blank;
230         fb->unblank = cg3_unblank;
231         
232         fb->physbase = phys;
233         fb->mmap_map = cg3_mmap_map;
234         
235 #ifdef __sparc_v9__     
236         sprintf(idstring, "%s at %016lx", cgRDI ? "cgRDI" : "cgthree", phys);
237 #else
238         sprintf(idstring, "%s at %x.%08lx", cgRDI ? "cgRDI" : "cgthree", fb->iospace, phys);
239 #endif
240         
241         if (!prom_getbool(fb->prom_node, "width")) {
242                 /* Ugh, broken PROM didn't initialize us.
243                  * Let's deal with this ourselves.
244                  */
245                 enum cg3_type type;
246                 u8 *p;
247 
248                 if (cgRDI)
249                         type = CG3_RDI;
250                 else {
251                         u8 status = sbus_readb(&fb->s.cg3.regs->status), mon;
252                         if ((status & CG3_SR_ID_MASK) == CG3_SR_ID_COLOR) {
253                                 mon = status & CG3_SR_RES_MASK;
254                                 if (mon == CG3_SR_1152_900_76_A ||
255                                     mon == CG3_SR_1152_900_76_B)
256                                         type = CG3_AT_76HZ;
257                                 else
258                                         type = CG3_AT_66HZ;
259                         } else {
260                                 prom_printf("cgthree: can't handle SR %02x\n",
261                                             status);
262                                 prom_halt();
263                                 return NULL; /* fool gcc. */
264                         }
265                 }
266 
267                 for (p = cg3_regvals[type]; *p; p += 2) {
268                         u8 *regp = &((u8 *)fb->s.cg3.regs)[p[0]];
269                         sbus_writeb(p[1], regp);
270                 }
271                 for (p = cg3_dacvals; *p; p += 2) {
272                         volatile u8 *regp;
273 
274                         regp = (volatile u8 *)&fb->s.cg3.regs->cmap.addr;
275                         sbus_writeb(p[0], regp);
276                         regp = (volatile u8 *)&fb->s.cg3.regs->cmap.control;
277                         sbus_writeb(p[1], regp);
278                 }
279         }
280 
281         return idstring;
282 }
283 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.