1 /*
2 * $Id: hitfb.c,v 1.2 2000/07/04 06:24:46 yaegashi Exp $
3 * linux/drivers/video/hitfb.c -- Hitachi LCD frame buffer device
4 * (C) 1999 Mihai Spatar
5 * (C) 2000 YAEGASHI Takeshi
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file COPYING in the main directory of this archive for
9 * more details.
10 */
11
12 #include <linux/config.h>
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/sched.h>
16 #include <linux/errno.h>
17 #include <linux/string.h>
18 #include <linux/mm.h>
19 #include <linux/tty.h>
20 #include <linux/malloc.h>
21 #include <linux/delay.h>
22 #include <linux/nubus.h>
23 #include <linux/init.h>
24
25 #include <asm/uaccess.h>
26 #include <asm/pgtable.h>
27 #include <asm/io.h>
28
29 #include <linux/fb.h>
30
31 #include <video/fbcon.h>
32 #include <video/fbcon-cfb8.h>
33 #include <video/fbcon-cfb16.h>
34
35 #include <asm/hd64461.h>
36
37 #define CONFIG_SH_LCD_VIDEOBASE CONFIG_HD64461_IOBASE+0x2000000
38
39 /* These are for HP Jornada 680/690.
40 It is desired that they are configurable... */
41 #define CONFIG_SH_LCD_VIDEOSIZE 1024*1024
42 #define CONFIG_SH_LCD_HORZ 640
43 #define CONFIG_SH_LCD_VERT 240
44 #define CONFIG_SH_LCD_DEFAULTBPP 16
45
46 struct hitfb_info {
47 struct fb_info_gen gen;
48 };
49
50 struct hitfb_par
51 {
52 int x, y;
53 int bpp;
54 };
55
56 static struct hitfb_info fb_info;
57 static struct hitfb_par current_par;
58 static int current_par_valid = 0;
59 static struct display disp;
60
61 static union {
62 #ifdef FBCON_HAS_CFB16
63 u16 cfb16[16];
64 #endif
65 } fbcon_cmap;
66
67 unsigned long hit_videobase, hit_videosize;
68 static struct fb_var_screeninfo default_var;
69
70 int hitfb_init(void);
71
72 static void hitfb_set_par(struct hitfb_par *par, const struct fb_info *info);
73 static void hitfb_encode_var(struct fb_var_screeninfo *var,
74 struct hitfb_par *par,
75 const struct fb_info *info);
76
77
78 static void hitfb_detect(void)
79 {
80 struct hitfb_par par;
81
82 hit_videobase = CONFIG_SH_LCD_VIDEOBASE;
83 hit_videosize = CONFIG_SH_LCD_VIDEOSIZE;
84
85 par.x = CONFIG_SH_LCD_HORZ;
86 par.y = CONFIG_SH_LCD_VERT;
87 par.bpp = CONFIG_SH_LCD_DEFAULTBPP;
88
89 hitfb_set_par(&par, NULL);
90 hitfb_encode_var(&default_var, &par, NULL);
91 }
92
93 static int hitfb_encode_fix(struct fb_fix_screeninfo *fix,
94 struct hitfb_par *par,
95 const struct fb_info *info)
96 {
97 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
98
99 strcpy(fix->id, "Hitachi HD64461");
100 fix->smem_start = hit_videobase;
101 fix->smem_len = hit_videosize;
102 fix->type = FB_TYPE_PACKED_PIXELS;
103 fix->type_aux = 0;
104 fix->visual = FB_VISUAL_TRUECOLOR;
105 fix->xpanstep = 0;
106 fix->ypanstep = 0;
107 fix->ywrapstep = 0;
108
109 switch(par->bpp) {
110 default:
111 case 8:
112 fix->line_length = par->x;
113 break;
114 case 16:
115 fix->line_length = par->x*2;
116 break;
117 }
118
119 return 0;
120 }
121
122
123 static int hitfb_decode_var(struct fb_var_screeninfo *var,
124 struct hitfb_par *par,
125 const struct fb_info *info)
126 {
127 par->x = var->xres;
128 par->y = var->yres;
129 par->bpp = var->bits_per_pixel;
130 return 0;
131 }
132
133
134 static void hitfb_encode_var(struct fb_var_screeninfo *var,
135 struct hitfb_par *par,
136 const struct fb_info *info)
137 {
138 memset(var, 0, sizeof(*var));
139
140 var->xres = par->x;
141 var->yres = par->y;
142 var->xres_virtual = var->xres;
143 var->yres_virtual = var->yres;
144 var->xoffset = 0;
145 var->yoffset = 0;
146 var->bits_per_pixel = par->bpp;
147 var->grayscale = 0;
148 var->transp.offset = 0;
149 var->transp.length = 0;
150 var->transp.msb_right = 0;
151 var->nonstd = 0;
152 var->activate = 0;
153 var->height = -1;
154 var->width = -1;
155 var->vmode = FB_VMODE_NONINTERLACED;
156 var->pixclock = 0;
157 var->sync = 0;
158 var->left_margin = 0;
159 var->right_margin = 0;
160 var->upper_margin = 0;
161 var->lower_margin = 0;
162 var->hsync_len = 0;
163 var->vsync_len = 0;
164
165 switch (var->bits_per_pixel) {
166
167 case 8:
168 var->red.offset = 0;
169 var->red.length = 8;
170 var->green.offset = 0;
171 var->green.length = 8;
172 var->blue.offset = 0;
173 var->blue.length = 8;
174 var->transp.offset = 0;
175 var->transp.length = 0;
176 break;
177
178 case 16: /* RGB 565 */
179 var->red.offset = 11;
180 var->red.length = 5;
181 var->green.offset = 5;
182 var->green.length = 6;
183 var->blue.offset = 0;
184 var->blue.length = 5;
185 var->transp.offset = 0;
186 var->transp.length = 0;
187 break;
188 }
189
190 var->red.msb_right = 0;
191 var->green.msb_right = 0;
192 var->blue.msb_right = 0;
193 var->transp.msb_right = 0;
194 }
195
196
197 static void hitfb_get_par(struct hitfb_par *par, const struct fb_info *info)
198 {
199 *par = current_par;
200 }
201
202
203 static void hitfb_set_par(struct hitfb_par *par, const struct fb_info *info)
204 {
205 /* Set the hardware according to 'par'. */
206 current_par = *par;
207 current_par_valid = 1;
208 }
209
210
211 static int hitfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
212 u_int *transp, struct fb_info *info)
213 {
214 if (regno > 255)
215 return 1;
216
217 outw(regno<<8, HD64461_CPTRAR);
218 *red = inw(HD64461_CPTRDR)<<10;
219 *green = inw(HD64461_CPTRDR)<<10;
220 *blue = inw(HD64461_CPTRDR)<<10;
221 *transp = 0;
222
223 return 0;
224 }
225
226
227 static int hitfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
228 u_int transp, struct fb_info *info)
229 {
230 if (regno > 255)
231 return 1;
232
233 outw(regno<<8, HD64461_CPTWAR);
234 outw(red>>10, HD64461_CPTWDR);
235 outw(green>>10, HD64461_CPTWDR);
236 outw(blue>>10, HD64461_CPTWDR);
237
238 if(regno<16) {
239 switch(current_par.bpp) {
240 #ifdef FBCON_HAS_CFB16
241 case 16:
242 fbcon_cmap.cfb16[regno] =
243 ((red & 0xf800) ) |
244 ((green & 0xfc00) >> 5) |
245 ((blue & 0xf800) >> 11);
246 break;
247 #endif
248 }
249 }
250
251 return 0;
252 }
253
254 static int hitfb_blank(int blank_mode, const struct fb_info *info)
255 {
256 return 0;
257 }
258
259
260 static void hitfb_set_disp(const void *par, struct display *disp,
261 struct fb_info_gen *info)
262 {
263 disp->screen_base = (void *)hit_videobase;
264 switch(((struct hitfb_par *)par)->bpp) {
265 #ifdef FBCON_HAS_CFB8
266 case 8:
267 disp->dispsw = &fbcon_cfb8;
268 break;
269 #endif
270 #ifdef FBCON_HAS_CFB16
271 case 16:
272 disp->dispsw = &fbcon_cfb16;
273 disp->dispsw_data = fbcon_cmap.cfb16;
274 break;
275 #endif
276 default:
277 disp->dispsw = &fbcon_dummy;
278 }
279 }
280
281
282 struct fbgen_hwswitch hitfb_switch = {
283 hitfb_detect,
284 hitfb_encode_fix,
285 hitfb_decode_var,
286 hitfb_encode_var,
287 hitfb_get_par,
288 hitfb_set_par,
289 hitfb_getcolreg,
290 hitfb_setcolreg,
291 NULL,
292 hitfb_blank,
293 hitfb_set_disp
294 };
295
296 static struct fb_ops hitfb_ops = {
297 owner: THIS_MODULE,
298 fb_get_fix: fbgen_get_fix,
299 fb_get_var: fbgen_get_var,
300 fb_set_var: fbgen_set_var,
301 fb_get_cmap: fbgen_get_cmap,
302 fb_set_cmap: fbgen_set_cmap,
303 };
304
305
306 int __init hitfb_init(void)
307 {
308 strcpy(fb_info.gen.info.modename, "Hitachi HD64461");
309 fb_info.gen.info.node = -1;
310 fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
311 fb_info.gen.info.fbops = &hitfb_ops;
312 fb_info.gen.info.disp = &disp;
313 fb_info.gen.info.changevar = NULL;
314 fb_info.gen.info.switch_con = &fbgen_switch;
315 fb_info.gen.info.updatevar = &fbgen_update_var;
316 fb_info.gen.info.blank = &fbgen_blank;
317 fb_info.gen.parsize = sizeof(struct hitfb_par);
318 fb_info.gen.fbhw = &hitfb_switch;
319 fb_info.gen.fbhw->detect();
320
321 fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
322 disp.var.activate = FB_ACTIVATE_NOW;
323 fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
324 fbgen_set_disp(-1, &fb_info.gen);
325 fbgen_install_cmap(0, &fb_info.gen);
326
327 if(register_framebuffer(&fb_info.gen.info)<0) return -EINVAL;
328
329 printk(KERN_INFO "fb%d: %s frame buffer device\n",
330 GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename);
331
332 return 0;
333 }
334
335
336 void hitfb_cleanup(struct fb_info *info)
337 {
338 unregister_framebuffer(info);
339 }
340
341
342 #ifdef MODULE
343 int init_module(void)
344 {
345 return hitfb_init();
346 }
347
348 void cleanup_module(void)
349 {
350 hitfb_cleanup(void);
351 }
352 #endif
353
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.