aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/pmag-ba-fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/pmag-ba-fb.c')
-rw-r--r--drivers/video/pmag-ba-fb.c285
1 files changed, 183 insertions, 102 deletions
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index f8095588e99d..c98f1c8d7dc2 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -1,57 +1,55 @@
1/* 1/*
2 * linux/drivers/video/pmag-ba-fb.c 2 * linux/drivers/video/pmag-ba-fb.c
3 * 3 *
4 * PMAG-BA TurboChannel framebuffer card support ... derived from: 4 * PMAG-BA TURBOchannel Color Frame Buffer (CFB) card support,
5 * derived from:
5 * "HP300 Topcat framebuffer support (derived from macfb of all things) 6 * "HP300 Topcat framebuffer support (derived from macfb of all things)
6 * Phil Blundell <philb@gnu.org> 1998", the original code can be 7 * Phil Blundell <philb@gnu.org> 1998", the original code can be
7 * found in the file hpfb.c in the same directory. 8 * found in the file hpfb.c in the same directory.
8 * 9 *
9 * Based on digital document: 10 * Based on digital document:
10 * "PMAG-BA TURBOchannel Color Frame Buffer 11 * "PMAG-BA TURBOchannel Color Frame Buffer
11 * Functional Specification", Revision 1.2, August 27, 1990 12 * Functional Specification", Revision 1.2, August 27, 1990
12 * 13 *
13 * DECstation related code Copyright (C) 1999, 2000, 2001 by 14 * DECstation related code Copyright (C) 1999, 2000, 2001 by
14 * Michael Engel <engel@unix-ag.org>, 15 * Michael Engel <engel@unix-ag.org>,
15 * Karsten Merker <merker@linuxtag.org> and 16 * Karsten Merker <merker@linuxtag.org> and
16 * Harald Koerfgen. 17 * Harald Koerfgen.
17 * This file is subject to the terms and conditions of the GNU General 18 * Copyright (c) 2005 Maciej W. Rozycki
18 * Public License. See the file COPYING in the main directory of this
19 * archive for more details.
20 * 19 *
20 * This file is subject to the terms and conditions of the GNU General
21 * Public License. See the file COPYING in the main directory of this
22 * archive for more details.
21 */ 23 */
22#include <linux/module.h> 24
23#include <linux/kernel.h> 25#include <linux/compiler.h>
24#include <linux/sched.h>
25#include <linux/errno.h> 26#include <linux/errno.h>
26#include <linux/string.h>
27#include <linux/timer.h>
28#include <linux/mm.h>
29#include <linux/tty.h>
30#include <linux/slab.h>
31#include <linux/delay.h>
32#include <linux/init.h>
33#include <linux/fb.h> 27#include <linux/fb.h>
34#include <asm/bootinfo.h> 28#include <linux/init.h>
35#include <asm/dec/machtype.h> 29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/types.h>
32
33#include <asm/bug.h>
34#include <asm/io.h>
35#include <asm/system.h>
36
36#include <asm/dec/tc.h> 37#include <asm/dec/tc.h>
38
37#include <video/pmag-ba-fb.h> 39#include <video/pmag-ba-fb.h>
38 40
39struct pmag_ba_ramdac_regs { 41
40 unsigned char addr_low; 42struct pmagbafb_par {
41 unsigned char pad0[3]; 43 struct fb_info *next;
42 unsigned char addr_hi; 44 volatile void __iomem *mmio;
43 unsigned char pad1[3]; 45 volatile u32 __iomem *dac;
44 unsigned char data; 46 int slot;
45 unsigned char pad2[3];
46 unsigned char cmap;
47}; 47};
48 48
49/*
50 * Max 3 TURBOchannel slots -> max 3 PMAG-BA :)
51 */
52static struct fb_info pmagba_fb_info[3];
53 49
54static struct fb_var_screeninfo pmagbafb_defined = { 50static struct fb_info *root_pmagbafb_dev;
51
52static struct fb_var_screeninfo pmagbafb_defined __initdata = {
55 .xres = 1024, 53 .xres = 1024,
56 .yres = 864, 54 .yres = 864,
57 .xres_virtual = 1024, 55 .xres_virtual = 1024,
@@ -61,58 +59,71 @@ static struct fb_var_screeninfo pmagbafb_defined = {
61 .green.length = 8, 59 .green.length = 8,
62 .blue.length = 8, 60 .blue.length = 8,
63 .activate = FB_ACTIVATE_NOW, 61 .activate = FB_ACTIVATE_NOW,
64 .height = 274, 62 .height = -1,
65 .width = 195, 63 .width = -1,
66 .accel = FB_ACCEL_NONE, 64 .accel_flags = FB_ACCEL_NONE,
65 .pixclock = 14452,
66 .left_margin = 116,
67 .right_margin = 12,
68 .upper_margin = 34,
69 .lower_margin = 12,
70 .hsync_len = 128,
71 .vsync_len = 3,
72 .sync = FB_SYNC_ON_GREEN,
67 .vmode = FB_VMODE_NONINTERLACED, 73 .vmode = FB_VMODE_NONINTERLACED,
68}; 74};
69 75
70static struct fb_fix_screeninfo pmagbafb_fix = { 76static struct fb_fix_screeninfo pmagbafb_fix __initdata = {
71 .id = "PMAG-BA", 77 .id = "PMAG-BA",
72 .smem_len = (1024 * 864), 78 .smem_len = (1024 * 1024),
73 .type = FB_TYPE_PACKED_PIXELS, 79 .type = FB_TYPE_PACKED_PIXELS,
74 .visual = FB_VISUAL_PSEUDOCOLOR, 80 .visual = FB_VISUAL_PSEUDOCOLOR,
75 .line_length = 1024, 81 .line_length = 1024,
82 .mmio_len = PMAG_BA_SIZE - PMAG_BA_BT459,
76}; 83};
77 84
78/* 85
79 * Turn hardware cursor off 86static inline void dac_write(struct pmagbafb_par *par, unsigned int reg, u8 v)
80 */
81void pmagbafb_erase_cursor(struct pmag_ba_ramdac_regs *bt459_regs)
82{ 87{
83 bt459_regs->addr_low = 0; 88 writeb(v, par->dac + reg / 4);
84 bt459_regs->addr_hi = 3;
85 bt459_regs->data = 0;
86} 89}
87 90
91static inline u8 dac_read(struct pmagbafb_par *par, unsigned int reg)
92{
93 return readb(par->dac + reg / 4);
94}
95
96
88/* 97/*
89 * Set the palette. 98 * Set the palette.
90 */ 99 */
91static int pmagbafb_setcolreg(unsigned regno, unsigned red, unsigned green, 100static int pmagbafb_setcolreg(unsigned int regno, unsigned int red,
92 unsigned blue, unsigned transp, 101 unsigned int green, unsigned int blue,
93 struct fb_info *info) 102 unsigned int transp, struct fb_info *info)
94{ 103{
95 struct pmag_ba_ramdac_regs *bt459_regs = (struct pmag_ba_ramdac_regs *) info->par; 104 struct pmagbafb_par *par = info->par;
96 105
97 if (regno >= info->cmap.len) 106 BUG_ON(regno >= info->cmap.len);
98 return 1;
99 107
100 red >>= 8; /* The cmap fields are 16 bits */ 108 red >>= 8; /* The cmap fields are 16 bits */
101 green >>= 8; /* wide, but the harware colormap */ 109 green >>= 8; /* wide, but the hardware colormap */
102 blue >>= 8; /* registers are only 8 bits wide */ 110 blue >>= 8; /* registers are only 8 bits wide */
103 111
104 bt459_regs->addr_low = (__u8) regno; 112 mb();
105 bt459_regs->addr_hi = 0; 113 dac_write(par, BT459_ADDR_LO, regno);
106 bt459_regs->cmap = red; 114 dac_write(par, BT459_ADDR_HI, 0x00);
107 bt459_regs->cmap = green; 115 wmb();
108 bt459_regs->cmap = blue; 116 dac_write(par, BT459_CMAP, red);
117 wmb();
118 dac_write(par, BT459_CMAP, green);
119 wmb();
120 dac_write(par, BT459_CMAP, blue);
121
109 return 0; 122 return 0;
110} 123}
111 124
112static struct fb_ops pmagbafb_ops = { 125static struct fb_ops pmagbafb_ops = {
113 .owner = THIS_MODULE, 126 .owner = THIS_MODULE,
114 .fb_get_fix = gen_get_fix,
115 .fb_get_var = gen_get_var,
116 .fb_setcolreg = pmagbafb_setcolreg, 127 .fb_setcolreg = pmagbafb_setcolreg,
117 .fb_fillrect = cfb_fillrect, 128 .fb_fillrect = cfb_fillrect,
118 .fb_copyarea = cfb_copyarea, 129 .fb_copyarea = cfb_copyarea,
@@ -120,63 +131,133 @@ static struct fb_ops pmagbafb_ops = {
120 .fb_cursor = soft_cursor, 131 .fb_cursor = soft_cursor,
121}; 132};
122 133
123int __init pmagbafb_init_one(int slot) 134
135/*
136 * Turn the hardware cursor off.
137 */
138static void __init pmagbafb_erase_cursor(struct fb_info *info)
139{
140 struct pmagbafb_par *par = info->par;
141
142 mb();
143 dac_write(par, BT459_ADDR_LO, 0x00);
144 dac_write(par, BT459_ADDR_HI, 0x03);
145 wmb();
146 dac_write(par, BT459_DATA, 0x00);
147}
148
149
150static int __init pmagbafb_init_one(int slot)
124{ 151{
125 unsigned long base_addr = get_tc_base_addr(slot); 152 struct fb_info *info;
126 struct fb_info *info = &pmagba_fb_info[slot]; 153 struct pmagbafb_par *par;
127 struct display *disp = &pmagba_disp[slot]; 154 unsigned long base_addr;
128 155
129 printk("PMAG-BA framebuffer in slot %d\n", slot); 156 info = framebuffer_alloc(sizeof(struct pmagbafb_par), NULL);
130 /* 157 if (!info)
131 * Framebuffer display memory base address and friends 158 return -ENOMEM;
132 */ 159
133 pmagbafb_fix.smem_start = base_addr + PMAG_BA_ONBOARD_FBMEM_OFFSET; 160 par = info->par;
134 info->par = (base_addr + PMAG_BA_BT459_OFFSET); 161 par->slot = slot;
135 162 claim_tc_card(par->slot);
136 /* 163
137 * Configure the Bt459 RAM DAC 164 base_addr = get_tc_base_addr(par->slot);
138 */ 165
139 pmagbafb_erase_cursor((struct pmag_ba_ramdac_regs *) info->par); 166 par->next = root_pmagbafb_dev;
140 167 root_pmagbafb_dev = info;
141 /* 168
142 * Let there be consoles.. 169 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
143 */ 170 goto err_alloc;
171
144 info->fbops = &pmagbafb_ops; 172 info->fbops = &pmagbafb_ops;
173 info->fix = pmagbafb_fix;
145 info->var = pmagbafb_defined; 174 info->var = pmagbafb_defined;
146 info->fix = pmagbafb_fix;
147 info->screen_base = pmagbafb_fix.smem_start;
148 info->flags = FBINFO_DEFAULT; 175 info->flags = FBINFO_DEFAULT;
149 176
150 fb_alloc_cmap(&fb_info.cmap, 256, 0); 177 /* MMIO mapping setup. */
178 info->fix.mmio_start = base_addr;
179 par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
180 if (!par->mmio)
181 goto err_cmap;
182 par->dac = par->mmio + PMAG_BA_BT459;
183
184 /* Frame buffer mapping setup. */
185 info->fix.smem_start = base_addr + PMAG_BA_FBMEM;
186 info->screen_base = ioremap_nocache(info->fix.smem_start,
187 info->fix.smem_len);
188 if (!info->screen_base)
189 goto err_mmio_map;
190 info->screen_size = info->fix.smem_len;
191
192 pmagbafb_erase_cursor(info);
151 193
152 if (register_framebuffer(info) < 0) 194 if (register_framebuffer(info) < 0)
153 return 1; 195 goto err_smem_map;
196
197 pr_info("fb%d: %s frame buffer device in slot %d\n",
198 info->node, info->fix.id, par->slot);
199
154 return 0; 200 return 0;
201
202
203err_smem_map:
204 iounmap(info->screen_base);
205
206err_mmio_map:
207 iounmap(par->mmio);
208
209err_cmap:
210 fb_dealloc_cmap(&info->cmap);
211
212err_alloc:
213 root_pmagbafb_dev = par->next;
214 release_tc_card(par->slot);
215 framebuffer_release(info);
216 return -ENXIO;
155} 217}
156 218
157/* 219static void __exit pmagbafb_exit_one(void)
158 * Initialise the framebuffer 220{
159 */ 221 struct fb_info *info = root_pmagbafb_dev;
222 struct pmagbafb_par *par = info->par;
160 223
161int __init pmagbafb_init(void) 224 unregister_framebuffer(info);
225 iounmap(info->screen_base);
226 iounmap(par->mmio);
227 fb_dealloc_cmap(&info->cmap);
228 root_pmagbafb_dev = par->next;
229 release_tc_card(par->slot);
230 framebuffer_release(info);
231}
232
233
234/*
235 * Initialise the framebuffer.
236 */
237static int __init pmagbafb_init(void)
162{ 238{
163 int sid; 239 int count = 0;
164 int found = 0; 240 int slot;
165 241
166 if (fb_get_options("pmagbafb", NULL)) 242 if (fb_get_options("pmagbafb", NULL))
167 return -ENODEV; 243 return -ENXIO;
168 244
169 if (TURBOCHANNEL) { 245 while ((slot = search_tc_card("PMAG-BA")) >= 0) {
170 while ((sid = search_tc_card("PMAG-BA")) >= 0) { 246 if (pmagbafb_init_one(slot) < 0)
171 found = 1; 247 break;
172 claim_tc_card(sid); 248 count++;
173 pmagbafb_init_one(sid);
174 }
175 return found ? 0 : -ENODEV;
176 } else {
177 return -ENODEV;
178 } 249 }
250 return (count > 0) ? 0 : -ENXIO;
179} 251}
180 252
253static void __exit pmagbafb_exit(void)
254{
255 while (root_pmagbafb_dev)
256 pmagbafb_exit_one();
257}
258
259
181module_init(pmagbafb_init); 260module_init(pmagbafb_init);
261module_exit(pmagbafb_exit);
262
182MODULE_LICENSE("GPL"); 263MODULE_LICENSE("GPL");