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

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

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

  1 /* $Id: tcxfb.c,v 1.11 1999/11/19 09:57:21 davem Exp $
  2  * tcxfb.c: TCX 24/8bit 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) 1996 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 #include <asm/sbus.h>
 27 
 28 #include <video/fbcon-cfb8.h>
 29 
 30 /* THC definitions */
 31 #define TCX_THC_MISC_REV_SHIFT       16
 32 #define TCX_THC_MISC_REV_MASK        15
 33 #define TCX_THC_MISC_VSYNC_DIS       (1 << 25)
 34 #define TCX_THC_MISC_HSYNC_DIS       (1 << 24)
 35 #define TCX_THC_MISC_RESET           (1 << 12)
 36 #define TCX_THC_MISC_VIDEO           (1 << 10)
 37 #define TCX_THC_MISC_SYNC            (1 << 9)
 38 #define TCX_THC_MISC_VSYNC           (1 << 8)
 39 #define TCX_THC_MISC_SYNC_ENAB       (1 << 7)
 40 #define TCX_THC_MISC_CURS_RES        (1 << 6)
 41 #define TCX_THC_MISC_INT_ENAB        (1 << 5)
 42 #define TCX_THC_MISC_INT             (1 << 4)
 43 #define TCX_THC_MISC_INIT            0x9f
 44 #define TCX_THC_REV_REV_SHIFT        20
 45 #define TCX_THC_REV_REV_MASK         15
 46 #define TCX_THC_REV_MINREV_SHIFT     28
 47 #define TCX_THC_REV_MINREV_MASK      15
 48 
 49 /* The contents are unknown */
 50 struct tcx_tec {
 51         volatile u32 tec_matrix;
 52         volatile u32 tec_clip;
 53         volatile u32 tec_vdc;
 54 };
 55 
 56 struct tcx_thc {
 57         volatile u32 thc_rev;
 58         u32 thc_pad0[511];
 59         volatile u32 thc_hs;            /* hsync timing */
 60         volatile u32 thc_hsdvs;
 61         volatile u32 thc_hd;
 62         volatile u32 thc_vs;            /* vsync timing */
 63         volatile u32 thc_vd;
 64         volatile u32 thc_refresh;
 65         volatile u32 thc_misc;
 66         u32 thc_pad1[56];
 67         volatile u32 thc_cursxy;        /* cursor x,y position (16 bits each) */
 68         volatile u32 thc_cursmask[32];  /* cursor mask bits */
 69         volatile u32 thc_cursbits[32];  /* what to show where mask enabled */
 70 };
 71 
 72 static struct sbus_mmap_map tcx_mmap_map[] = {
 73         { TCX_RAM8BIT,          0,              SBUS_MMAP_FBSIZE(1) },
 74         { TCX_RAM24BIT,         0,              SBUS_MMAP_FBSIZE(4) },
 75         { TCX_UNK3,             0,              SBUS_MMAP_FBSIZE(8) },
 76         { TCX_UNK4,             0,              SBUS_MMAP_FBSIZE(8) },
 77         { TCX_CONTROLPLANE,     0,              SBUS_MMAP_FBSIZE(4) },
 78         { TCX_UNK6,             0,              SBUS_MMAP_FBSIZE(8) },
 79         { TCX_UNK7,             0,              SBUS_MMAP_FBSIZE(8) },
 80         { TCX_TEC,              0,              PAGE_SIZE           },
 81         { TCX_BTREGS,           0,              PAGE_SIZE           },
 82         { TCX_THC,              0,              PAGE_SIZE           },
 83         { TCX_DHC,              0,              PAGE_SIZE           },
 84         { TCX_ALT,              0,              PAGE_SIZE           },
 85         { TCX_UNK2,             0,              0x20000             },
 86         { 0,                    0,              0                   }
 87 };
 88 
 89 static void __tcx_set_control_plane (struct fb_info_sbusfb *fb)
 90 {
 91         u32 *p, *pend;
 92         
 93         p = fb->s.tcx.cplane;
 94         if (p == NULL)
 95                 return;
 96         for (pend = p + fb->type.fb_size; p < pend; p++) {
 97                 u32 tmp = sbus_readl(p);
 98 
 99                 tmp &= 0xffffff;
100                 sbus_writel(tmp, p);
101         }
102 }
103                                                 
104 static void tcx_switch_from_graph (struct fb_info_sbusfb *fb)
105 {
106         unsigned long flags;
107 
108         spin_lock_irqsave(&fb->lock, flags);
109 
110         /* Reset control plane to 8bit mode if necessary */
111         if (fb->open && fb->mmaped)
112                 __tcx_set_control_plane (fb);
113 
114         spin_unlock_irqrestore(&fb->lock, flags);
115 }
116 
117 static void tcx_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
118 {
119         struct bt_regs *bt = fb->s.tcx.bt;
120         unsigned long flags;
121         int i;
122                 
123         spin_lock_irqsave(&fb->lock, flags);
124         sbus_writel(index << 24, &bt->addr);
125         for (i = index; count--; i++){
126                 sbus_writel(fb->color_map CM(i,0) << 24, &bt->color_map);
127                 sbus_writel(fb->color_map CM(i,1) << 24, &bt->color_map);
128                 sbus_writel(fb->color_map CM(i,2) << 24, &bt->color_map);
129         }
130         sbus_writel(0, &bt->addr);
131         spin_unlock_irqrestore(&fb->lock, flags);
132 }
133 
134 static void tcx_restore_palette (struct fb_info_sbusfb *fb)
135 {
136         struct bt_regs *bt = fb->s.tcx.bt;
137         unsigned long flags;
138                 
139         spin_lock_irqsave(&fb->lock, flags);
140         sbus_writel(0, &bt->addr);
141         sbus_writel(0xffffffff, &bt->color_map);
142         sbus_writel(0xffffffff, &bt->color_map);
143         sbus_writel(0xffffffff, &bt->color_map);
144         spin_unlock_irqrestore(&fb->lock, flags);
145 }
146 
147 static void tcx_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
148 {
149         struct bt_regs *bt = fb->s.tcx.bt;
150         unsigned long flags;
151 
152         spin_lock_irqsave(&fb->lock, flags);
153 
154         /* Note the 2 << 24 is different from cg6's 1 << 24 */
155         sbus_writel(2 << 24, &bt->addr);
156         sbus_writel(red[0] << 24, &bt->cursor);
157         sbus_writel(green[0] << 24, &bt->cursor);
158         sbus_writel(blue[0] << 24, &bt->cursor);
159         sbus_writel(3 << 24, &bt->addr);
160         sbus_writel(red[1] << 24, &bt->cursor);
161         sbus_writel(green[1] << 24, &bt->cursor);
162         sbus_writel(blue[1] << 24, &bt->cursor);
163         sbus_writel(0, &bt->addr);
164 
165         spin_unlock_irqrestore(&fb->lock, flags);
166 }
167 
168 /* Set cursor shape */
169 static void tcx_setcurshape (struct fb_info_sbusfb *fb)
170 {
171         struct tcx_thc *thc = fb->s.tcx.thc;
172         unsigned long flags;
173         int i;
174 
175         spin_lock_irqsave(&fb->lock, flags);
176         for (i = 0; i < 32; i++){
177                 sbus_writel(fb->cursor.bits[0][i], &thc->thc_cursmask[i]);
178                 sbus_writel(fb->cursor.bits[1][i], &thc->thc_cursbits[i]);
179         }
180         spin_unlock_irqrestore(&fb->lock, flags);
181 }
182 
183 /* Load cursor information */
184 static void tcx_setcursor (struct fb_info_sbusfb *fb)
185 {
186         struct cg_cursor *c = &fb->cursor;
187         unsigned long flags;
188         unsigned int v;
189 
190         spin_lock_irqsave(&fb->lock, flags);
191         if (c->enable)
192                 v = ((c->cpos.fbx - c->chot.fbx) << 16)
193                     |((c->cpos.fby - c->chot.fby) & 0xffff);
194         else
195                 /* Magic constant to turn off the cursor */
196                 v = ((65536-32) << 16) | (65536-32);
197         sbus_writel(v, &fb->s.tcx.thc->thc_cursxy);
198         spin_unlock_irqrestore(&fb->lock, flags);
199 }
200 
201 static void tcx_blank (struct fb_info_sbusfb *fb)
202 {
203         unsigned long flags;
204         u32 tmp;
205 
206         spin_lock_irqsave(&fb->lock, flags);
207         tmp = sbus_readl(&fb->s.tcx.thc->thc_misc);
208         tmp &= ~TCX_THC_MISC_VIDEO;
209         /* This should put us in power-save */
210         tmp |= TCX_THC_MISC_VSYNC_DIS;
211         tmp |= TCX_THC_MISC_HSYNC_DIS;
212         sbus_writel(tmp, &fb->s.tcx.thc->thc_misc);
213         spin_unlock_irqrestore(&fb->lock, flags);
214 }
215 
216 static void tcx_unblank (struct fb_info_sbusfb *fb)
217 {
218         unsigned long flags;
219         u32 tmp;
220 
221         spin_lock_irqsave(&fb->lock, flags);
222         tmp = sbus_readl(&fb->s.tcx.thc->thc_misc);
223         tmp &= ~TCX_THC_MISC_VSYNC_DIS;
224         tmp &= ~TCX_THC_MISC_HSYNC_DIS;
225         tmp |= TCX_THC_MISC_VIDEO;
226         sbus_writel(tmp, &fb->s.tcx.thc->thc_misc);
227         spin_unlock_irqrestore(&fb->lock, flags);
228 }
229 
230 static void tcx_reset (struct fb_info_sbusfb *fb)
231 {
232         unsigned long flags;
233         u32 tmp;
234 
235         spin_lock_irqsave(&fb->lock, flags);
236         if (fb->open && fb->mmaped)
237                 __tcx_set_control_plane(fb);
238         
239         /* Turn off stuff in the Transform Engine. */
240         sbus_writel(0, &fb->s.tcx.tec->tec_matrix);
241         sbus_writel(0, &fb->s.tcx.tec->tec_clip);
242         sbus_writel(0, &fb->s.tcx.tec->tec_vdc);
243 
244         /* Enable cursor in Brooktree DAC. */
245         sbus_writel(0x06 << 24, &fb->s.tcx.bt->addr);
246         tmp = sbus_readl(&fb->s.tcx.bt->control);
247         tmp |= 0x03 << 24;
248         sbus_writel(tmp, &fb->s.tcx.bt->control);
249         spin_unlock_irqrestore(&fb->lock, flags);
250 }
251 
252 static void tcx_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
253 {
254         p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin);
255 }
256 
257 static char idstring[60] __initdata = { 0 };
258 
259 char __init *tcxfb_init(struct fb_info_sbusfb *fb)
260 {
261         struct fb_fix_screeninfo *fix = &fb->fix;
262         struct display *disp = &fb->disp;
263         struct fbtype *type = &fb->type;
264         struct sbus_dev *sdev = fb->sbdp;
265         unsigned long phys = sdev->reg_addrs[0].phys_addr;
266         int lowdepth, i, j;
267 
268 #ifndef FBCON_HAS_CFB8
269         return NULL;
270 #endif
271 
272         lowdepth = prom_getbool (fb->prom_node, "tcx-8-bit");
273 
274         if (lowdepth) {
275                 strcpy(fb->info.modename, "TCX8");
276                 strcpy(fix->id, "TCX8");
277         } else {
278                 strcpy(fb->info.modename, "TCX24");
279                 strcpy(fix->id, "TCX24");
280         }
281         fix->line_length = fb->var.xres_virtual;
282         fix->accel = FB_ACCEL_SUN_TCX;
283 
284         disp->scrollmode = SCROLL_YREDRAW;
285         if (!disp->screen_base) {
286                 disp->screen_base = (char *)
287                         sbus_ioremap(&sdev->resource[0], 0,
288                                      type->fb_size, "tcx ram");
289         }
290         disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
291         fb->s.tcx.tec = (struct tcx_tec *)
292                 sbus_ioremap(&sdev->resource[7], 0,
293                              sizeof(struct tcx_tec), "tcx tec");
294         fb->s.tcx.thc = (struct tcx_thc *)
295                 sbus_ioremap(&sdev->resource[9], 0,
296                              sizeof(struct tcx_thc), "tcx thc");
297         fb->s.tcx.bt = (struct bt_regs *)
298                 sbus_ioremap(&sdev->resource[8], 0, 
299                              sizeof(struct bt_regs), "tcx dac");
300         if (!lowdepth) {
301                 fb->s.tcx.cplane = (u32 *)
302                         sbus_ioremap(&sdev->resource[4], 0, 
303                                      type->fb_size * sizeof(u32), "tcx cplane");
304                 type->fb_depth = 24;
305                 fb->switch_from_graph = tcx_switch_from_graph;
306         } else {
307                 /* As there can be one tcx in a machine only, we can write directly into
308                    tcx_mmap_map */
309                 tcx_mmap_map[1].size = SBUS_MMAP_EMPTY;
310                 tcx_mmap_map[4].size = SBUS_MMAP_EMPTY;
311                 tcx_mmap_map[5].size = SBUS_MMAP_EMPTY;
312                 tcx_mmap_map[6].size = SBUS_MMAP_EMPTY;
313         }
314         fb->dispsw = fbcon_cfb8;
315 
316         fb->margins = tcx_margins;
317         fb->loadcmap = tcx_loadcmap;
318         if (prom_getbool (fb->prom_node, "hw-cursor")) {
319                 fb->setcursor = tcx_setcursor;
320                 fb->setcursormap = tcx_setcursormap;
321                 fb->setcurshape = tcx_setcurshape;
322         }
323         fb->restore_palette = tcx_restore_palette;
324         fb->blank = tcx_blank;
325         fb->unblank = tcx_unblank;
326         fb->reset = tcx_reset;
327 
328         fb->physbase = 0;
329         for (i = 0; i < 13; i++) {
330                 /* tcx_mmap_map has to be sorted by voff, while
331                    order of phys registers from PROM differs a little
332                    bit. Here is the correction */
333                 switch (i) {
334                 case 10: j = 12; break;
335                 case 11:
336                 case 12: j = i - 1; break;
337                 default: j = i; break;
338                 }
339                 tcx_mmap_map[i].poff = fb->sbdp->reg_addrs[j].phys_addr;
340         }
341         fb->mmap_map = tcx_mmap_map;
342 
343         /* Initialize Brooktree DAC */
344         sbus_writel(0x04 << 24, &fb->s.tcx.bt->addr);         /* color planes */
345         sbus_writel(0xff << 24, &fb->s.tcx.bt->control);
346         sbus_writel(0x05 << 24, &fb->s.tcx.bt->addr);
347         sbus_writel(0x00 << 24, &fb->s.tcx.bt->control);
348         sbus_writel(0x06 << 24, &fb->s.tcx.bt->addr);         /* overlay plane */
349         sbus_writel(0x73 << 24, &fb->s.tcx.bt->control);
350         sbus_writel(0x07 << 24, &fb->s.tcx.bt->addr);
351         sbus_writel(0x00 << 24, &fb->s.tcx.bt->control);
352 
353         sprintf(idstring, "tcx at %x.%08lx Rev %d.%d %s",
354                 fb->iospace, phys,
355                 ((sbus_readl(&fb->s.tcx.thc->thc_rev) >> TCX_THC_REV_REV_SHIFT) &
356                  TCX_THC_REV_REV_MASK),
357                 ((sbus_readl(&fb->s.tcx.thc->thc_rev) >> TCX_THC_REV_MINREV_SHIFT) &
358                  TCX_THC_REV_MINREV_MASK),
359                 lowdepth ? "8-bit only" : "24-bit depth");
360                     
361         tcx_reset(fb);
362 
363         return idstring;
364 }
365 

~ [ 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.