1 /* cg14.c: CGFOURTEEN frame buffer driver
3 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
5 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
7 * Driver layout based loosely on tgafb.c, see that file for credits.
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/errno.h>
13 #include <linux/string.h>
14 #include <linux/slab.h>
15 #include <linux/delay.h>
16 #include <linux/init.h>
22 #include <asm/of_device.h>
31 static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned,
32 unsigned, struct fb_info
*);
34 static int cg14_mmap(struct fb_info
*, struct vm_area_struct
*);
35 static int cg14_ioctl(struct fb_info
*, unsigned int, unsigned long);
36 static int cg14_pan_display(struct fb_var_screeninfo
*, struct fb_info
*);
39 * Frame buffer operations
42 static struct fb_ops cg14_ops
= {
44 .fb_setcolreg
= cg14_setcolreg
,
45 .fb_pan_display
= cg14_pan_display
,
46 .fb_fillrect
= cfb_fillrect
,
47 .fb_copyarea
= cfb_copyarea
,
48 .fb_imageblit
= cfb_imageblit
,
50 .fb_ioctl
= cg14_ioctl
,
52 .fb_compat_ioctl
= sbusfb_compat_ioctl
,
56 #define CG14_MCR_INTENABLE_SHIFT 7
57 #define CG14_MCR_INTENABLE_MASK 0x80
58 #define CG14_MCR_VIDENABLE_SHIFT 6
59 #define CG14_MCR_VIDENABLE_MASK 0x40
60 #define CG14_MCR_PIXMODE_SHIFT 4
61 #define CG14_MCR_PIXMODE_MASK 0x30
62 #define CG14_MCR_TMR_SHIFT 2
63 #define CG14_MCR_TMR_MASK 0x0c
64 #define CG14_MCR_TMENABLE_SHIFT 1
65 #define CG14_MCR_TMENABLE_MASK 0x02
66 #define CG14_MCR_RESET_SHIFT 0
67 #define CG14_MCR_RESET_MASK 0x01
68 #define CG14_REV_REVISION_SHIFT 4
69 #define CG14_REV_REVISION_MASK 0xf0
70 #define CG14_REV_IMPL_SHIFT 0
71 #define CG14_REV_IMPL_MASK 0x0f
72 #define CG14_VBR_FRAMEBASE_SHIFT 12
73 #define CG14_VBR_FRAMEBASE_MASK 0x00fff000
74 #define CG14_VMCR1_SETUP_SHIFT 0
75 #define CG14_VMCR1_SETUP_MASK 0x000001ff
76 #define CG14_VMCR1_VCONFIG_SHIFT 9
77 #define CG14_VMCR1_VCONFIG_MASK 0x00000e00
78 #define CG14_VMCR2_REFRESH_SHIFT 0
79 #define CG14_VMCR2_REFRESH_MASK 0x00000001
80 #define CG14_VMCR2_TESTROWCNT_SHIFT 1
81 #define CG14_VMCR2_TESTROWCNT_MASK 0x00000002
82 #define CG14_VMCR2_FBCONFIG_SHIFT 2
83 #define CG14_VMCR2_FBCONFIG_MASK 0x0000000c
84 #define CG14_VCR_REFRESHREQ_SHIFT 0
85 #define CG14_VCR_REFRESHREQ_MASK 0x000003ff
86 #define CG14_VCR1_REFRESHENA_SHIFT 10
87 #define CG14_VCR1_REFRESHENA_MASK 0x00000400
88 #define CG14_VCA_CAD_SHIFT 0
89 #define CG14_VCA_CAD_MASK 0x000003ff
90 #define CG14_VCA_VERS_SHIFT 10
91 #define CG14_VCA_VERS_MASK 0x00000c00
92 #define CG14_VCA_RAMSPEED_SHIFT 12
93 #define CG14_VCA_RAMSPEED_MASK 0x00001000
94 #define CG14_VCA_8MB_SHIFT 13
95 #define CG14_VCA_8MB_MASK 0x00002000
97 #define CG14_MCR_PIXMODE_8 0
98 #define CG14_MCR_PIXMODE_16 2
99 #define CG14_MCR_PIXMODE_32 3
102 u8 mcr
; /* Master Control Reg */
103 u8 ppr
; /* Packed Pixel Reg */
104 u8 tms
[2]; /* Test Mode Status Regs */
105 u8 msr
; /* Master Status Reg */
106 u8 fsr
; /* Fault Status Reg */
107 u8 rev
; /* Revision & Impl */
108 u8 ccr
; /* Clock Control Reg */
109 u32 tmr
; /* Test Mode Read Back */
110 u8 mod
; /* Monitor Operation Data Reg */
111 u8 acr
; /* Aux Control */
113 u16 hct
; /* Hor Counter */
114 u16 vct
; /* Vert Counter */
115 u16 hbs
; /* Hor Blank Start */
116 u16 hbc
; /* Hor Blank Clear */
117 u16 hss
; /* Hor Sync Start */
118 u16 hsc
; /* Hor Sync Clear */
119 u16 csc
; /* Composite Sync Clear */
120 u16 vbs
; /* Vert Blank Start */
121 u16 vbc
; /* Vert Blank Clear */
122 u16 vss
; /* Vert Sync Start */
123 u16 vsc
; /* Vert Sync Clear */
126 u16 fsa
; /* Fault Status Address */
127 u16 adr
; /* Address Registers */
129 u8 pcg
[0x100]; /* Pixel Clock Generator */
130 u32 vbr
; /* Frame Base Row */
131 u32 vmcr
; /* VBC Master Control */
132 u32 vcr
; /* VBC refresh */
133 u32 vca
; /* VBC Config */
136 #define CG14_CCR_ENABLE 0x04
137 #define CG14_CCR_SELECT 0x02 /* HW/Full screen */
140 u32 cpl0
[32]; /* Enable plane 0 */
141 u32 cpl1
[32]; /* Color selection plane */
142 u8 ccr
; /* Cursor Control Reg */
144 u16 cursx
; /* Cursor x,y position */
145 u16 cursy
; /* Cursor x,y position */
149 u32 cpl0i
[32]; /* Enable plane 0 autoinc */
150 u32 cpl1i
[32]; /* Color selection autoinc */
154 u8 addr
; /* Address Register */
156 u8 glut
; /* Gamma table */
158 u8 select
; /* Register Select */
160 u8 mode
; /* Mode Register */
168 u8 x_xlutd_inc
[256];
171 /* Color look up table (clut) */
172 /* Each one of these arrays hold the color lookup table (for 256
173 * colors) for each MDI page (I assume then there should be 4 MDI
174 * pages, I still wonder what they are. I have seen NeXTStep split
175 * the screen in four parts, while operating in 24 bits mode. Each
176 * integer holds 4 values: alpha value (transparency channel, thanks
177 * go to John Stone (johns@umr.edu) from OpenBSD), red, green and blue
179 * I currently use the clut instead of the Xlut
183 u32 c_clutd
[256]; /* i wonder what the 'd' is for */
184 u32 c_clut_inc
[256];
185 u32 c_clutd_inc
[256];
188 #define CG14_MMAP_ENTRIES 16
192 struct cg14_regs __iomem
*regs
;
193 struct cg14_clut __iomem
*clut
;
194 struct cg14_cursor __iomem
*cursor
;
197 #define CG14_FLAG_BLANKED 0x00000001
199 unsigned long physbase
;
200 unsigned long iospace
;
201 unsigned long fbsize
;
203 struct sbus_mmap_map mmap_map
[CG14_MMAP_ENTRIES
];
209 static void __cg14_reset(struct cg14_par
*par
)
211 struct cg14_regs __iomem
*regs
= par
->regs
;
214 val
= sbus_readb(®s
->mcr
);
215 val
&= ~(CG14_MCR_PIXMODE_MASK
);
216 sbus_writeb(val
, ®s
->mcr
);
219 static int cg14_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
221 struct cg14_par
*par
= (struct cg14_par
*) info
->par
;
224 /* We just use this to catch switches out of
227 spin_lock_irqsave(&par
->lock
, flags
);
229 spin_unlock_irqrestore(&par
->lock
, flags
);
231 if (var
->xoffset
|| var
->yoffset
|| var
->vmode
)
237 * cg14_setcolreg - Optional function. Sets a color register.
238 * @regno: boolean, 0 copy local, 1 get_user() function
239 * @red: frame buffer colormap structure
240 * @green: The green value which can be up to 16 bits wide
241 * @blue: The blue value which can be up to 16 bits wide.
242 * @transp: If supported the alpha value which can be up to 16 bits wide.
243 * @info: frame buffer info structure
245 static int cg14_setcolreg(unsigned regno
,
246 unsigned red
, unsigned green
, unsigned blue
,
247 unsigned transp
, struct fb_info
*info
)
249 struct cg14_par
*par
= (struct cg14_par
*) info
->par
;
250 struct cg14_clut __iomem
*clut
= par
->clut
;
260 val
= (red
| (green
<< 8) | (blue
<< 16));
262 spin_lock_irqsave(&par
->lock
, flags
);
263 sbus_writel(val
, &clut
->c_clut
[regno
]);
264 spin_unlock_irqrestore(&par
->lock
, flags
);
269 static int cg14_mmap(struct fb_info
*info
, struct vm_area_struct
*vma
)
271 struct cg14_par
*par
= (struct cg14_par
*) info
->par
;
273 return sbusfb_mmap_helper(par
->mmap_map
,
274 par
->physbase
, par
->fbsize
,
278 static int cg14_ioctl(struct fb_info
*info
, unsigned int cmd
, unsigned long arg
)
280 struct cg14_par
*par
= (struct cg14_par
*) info
->par
;
281 struct cg14_regs __iomem
*regs
= par
->regs
;
282 struct mdi_cfginfo kmdi
, __user
*mdii
;
284 int cur_mode
, mode
, ret
= 0;
288 spin_lock_irqsave(&par
->lock
, flags
);
290 spin_unlock_irqrestore(&par
->lock
, flags
);
293 case MDI_GET_CFGINFO
:
294 memset(&kmdi
, 0, sizeof(kmdi
));
296 spin_lock_irqsave(&par
->lock
, flags
);
297 kmdi
.mdi_type
= FBTYPE_MDICOLOR
;
298 kmdi
.mdi_height
= info
->var
.yres
;
299 kmdi
.mdi_width
= info
->var
.xres
;
300 kmdi
.mdi_mode
= par
->mode
;
301 kmdi
.mdi_pixfreq
= 72; /* FIXME */
302 kmdi
.mdi_size
= par
->ramsize
;
303 spin_unlock_irqrestore(&par
->lock
, flags
);
305 mdii
= (struct mdi_cfginfo __user
*) arg
;
306 if (copy_to_user(mdii
, &kmdi
, sizeof(kmdi
)))
310 case MDI_SET_PIXELMODE
:
311 if (get_user(mode
, (int __user
*) arg
)) {
316 spin_lock_irqsave(&par
->lock
, flags
);
317 cur_mode
= sbus_readb(®s
->mcr
);
318 cur_mode
&= ~CG14_MCR_PIXMODE_MASK
;
321 cur_mode
|= (CG14_MCR_PIXMODE_32
<<
322 CG14_MCR_PIXMODE_SHIFT
);
326 cur_mode
|= (CG14_MCR_PIXMODE_16
<<
327 CG14_MCR_PIXMODE_SHIFT
);
338 sbus_writeb(cur_mode
, ®s
->mcr
);
341 spin_unlock_irqrestore(&par
->lock
, flags
);
345 ret
= sbusfb_ioctl_helper(cmd
, arg
, info
,
346 FBTYPE_MDICOLOR
, 8, par
->fbsize
);
357 static void cg14_init_fix(struct fb_info
*info
, int linebytes
, struct device_node
*dp
)
359 const char *name
= dp
->name
;
361 strlcpy(info
->fix
.id
, name
, sizeof(info
->fix
.id
));
363 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
364 info
->fix
.visual
= FB_VISUAL_PSEUDOCOLOR
;
366 info
->fix
.line_length
= linebytes
;
368 info
->fix
.accel
= FB_ACCEL_SUN_CG14
;
371 static struct sbus_mmap_map __cg14_mmap_map
[CG14_MMAP_ENTRIES
] __initdata
= {
398 .voff
= CG3_MMAP_OFFSET
- 0x7000,
403 .voff
= CG3_MMAP_OFFSET
,
405 .size
= SBUS_MMAP_FBSIZE(1)
408 .voff
= MDI_CURSOR_MAP
,
413 .voff
= MDI_CHUNKY_BGR_MAP
,
418 .voff
= MDI_PLANAR_X16_MAP
,
423 .voff
= MDI_PLANAR_C16_MAP
,
428 .voff
= MDI_PLANAR_X32_MAP
,
433 .voff
= MDI_PLANAR_B32_MAP
,
438 .voff
= MDI_PLANAR_G32_MAP
,
443 .voff
= MDI_PLANAR_R32_MAP
,
455 static void cg14_unmap_regs(struct all_info
*all
)
458 of_iounmap(all
->par
.regs
, sizeof(struct cg14_regs
));
460 of_iounmap(all
->par
.clut
, sizeof(struct cg14_clut
));
462 of_iounmap(all
->par
.cursor
, sizeof(struct cg14_cursor
));
463 if (all
->info
.screen_base
)
464 of_iounmap(all
->info
.screen_base
, all
->par
.fbsize
);
467 static int __devinit
cg14_init_one(struct of_device
*op
)
469 struct device_node
*dp
= op
->node
;
470 struct all_info
*all
;
471 int is_8mb
, linebytes
, i
, err
;
473 all
= kzalloc(sizeof(*all
), GFP_KERNEL
);
477 spin_lock_init(&all
->par
.lock
);
479 sbusfb_fill_var(&all
->info
.var
, dp
->node
, 8);
480 all
->info
.var
.red
.length
= 8;
481 all
->info
.var
.green
.length
= 8;
482 all
->info
.var
.blue
.length
= 8;
484 linebytes
= of_getintprop_default(dp
, "linebytes",
486 all
->par
.fbsize
= PAGE_ALIGN(linebytes
* all
->info
.var
.yres
);
488 if (!strcmp(dp
->parent
->name
, "sbus") ||
489 !strcmp(dp
->parent
->name
, "sbi")) {
490 all
->par
.physbase
= op
->resource
[0].start
;
491 all
->par
.iospace
= op
->resource
[0].flags
& IORESOURCE_BITS
;
493 all
->par
.physbase
= op
->resource
[1].start
;
494 all
->par
.iospace
= op
->resource
[0].flags
& IORESOURCE_BITS
;
497 all
->par
.regs
= of_ioremap(&op
->resource
[0], 0,
498 sizeof(struct cg14_regs
), "cg14 regs");
499 all
->par
.clut
= of_ioremap(&op
->resource
[0], CG14_CLUT1
,
500 sizeof(struct cg14_clut
), "cg14 clut");
501 all
->par
.cursor
= of_ioremap(&op
->resource
[0], CG14_CURSORREGS
,
502 sizeof(struct cg14_cursor
), "cg14 cursor");
504 all
->info
.screen_base
= of_ioremap(&op
->resource
[1], 0,
505 all
->par
.fbsize
, "cg14 ram");
507 if (!all
->par
.regs
|| !all
->par
.clut
|| !all
->par
.cursor
||
508 !all
->info
.screen_base
)
509 cg14_unmap_regs(all
);
511 is_8mb
= (((op
->resource
[1].end
- op
->resource
[1].start
) + 1) ==
514 BUILD_BUG_ON(sizeof(all
->par
.mmap_map
) != sizeof(__cg14_mmap_map
));
516 memcpy(&all
->par
.mmap_map
, &__cg14_mmap_map
,
517 sizeof(all
->par
.mmap_map
));
519 for (i
= 0; i
< CG14_MMAP_ENTRIES
; i
++) {
520 struct sbus_mmap_map
*map
= &all
->par
.mmap_map
[i
];
524 if (map
->poff
& 0x80000000)
525 map
->poff
= (map
->poff
& 0x7fffffff) +
526 (op
->resource
[0].start
-
527 op
->resource
[1].start
);
529 map
->size
>= 0x100000 &&
530 map
->size
<= 0x400000)
534 all
->par
.mode
= MDI_8_PIX
;
535 all
->par
.ramsize
= (is_8mb
? 0x800000 : 0x400000);
537 all
->info
.flags
= FBINFO_DEFAULT
| FBINFO_HWACCEL_YPAN
;
538 all
->info
.fbops
= &cg14_ops
;
539 all
->info
.par
= &all
->par
;
541 __cg14_reset(&all
->par
);
543 if (fb_alloc_cmap(&all
->info
.cmap
, 256, 0)) {
544 cg14_unmap_regs(all
);
548 fb_set_cmap(&all
->info
.cmap
, &all
->info
);
550 cg14_init_fix(&all
->info
, linebytes
, dp
);
552 err
= register_framebuffer(&all
->info
);
554 fb_dealloc_cmap(&all
->info
.cmap
);
555 cg14_unmap_regs(all
);
560 dev_set_drvdata(&op
->dev
, all
);
562 printk("%s: cgfourteen at %lx:%lx, %dMB\n",
564 all
->par
.iospace
, all
->par
.physbase
,
565 all
->par
.ramsize
>> 20);
570 static int __devinit
cg14_probe(struct of_device
*dev
, const struct of_device_id
*match
)
572 struct of_device
*op
= to_of_device(&dev
->dev
);
574 return cg14_init_one(op
);
577 static int __devexit
cg14_remove(struct of_device
*dev
)
579 struct all_info
*all
= dev_get_drvdata(&dev
->dev
);
581 unregister_framebuffer(&all
->info
);
582 fb_dealloc_cmap(&all
->info
.cmap
);
584 cg14_unmap_regs(all
);
588 dev_set_drvdata(&dev
->dev
, NULL
);
593 static struct of_device_id cg14_match
[] = {
595 .name
= "cgfourteen",
599 MODULE_DEVICE_TABLE(of
, cg14_match
);
601 static struct of_platform_driver cg14_driver
= {
603 .match_table
= cg14_match
,
605 .remove
= __devexit_p(cg14_remove
),
608 int __init
cg14_init(void)
610 if (fb_get_options("cg14fb", NULL
))
613 return of_register_driver(&cg14_driver
, &of_bus_type
);
616 void __exit
cg14_exit(void)
618 of_unregister_driver(&cg14_driver
);
621 module_init(cg14_init
);
622 module_exit(cg14_exit
);
624 MODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets");
625 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
626 MODULE_VERSION("2.0");
627 MODULE_LICENSE("GPL");