1/* 2 * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device 3 * 4 * Created 28 Dec 1997 by Geert Uytterhoeven 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file COPYING in the main directory of this archive 8 * for more details. 9 */ 10 11#include <linux/module.h> 12#include <linux/kernel.h> 13#include <linux/errno.h> 14#include <linux/string.h> 15#include <linux/mm.h> 16#include <linux/tty.h> 17#include <linux/slab.h> 18#include <linux/delay.h> 19#include <linux/fb.h> 20#include <linux/init.h> 21 22#include <video/fbcon.h> 23 24 25 /* 26 * This is just simple sample code. 27 * 28 * No warranty that it actually compiles. 29 * Even less warranty that it actually works :-) 30 */ 31 32 33struct xxxfb_info { 34 /* 35 * Choose _one_ of the two alternatives: 36 * 37 * 1. Use the generic frame buffer operations (fbgen_*). 38 */ 39 struct fb_info_gen gen; 40 /* 41 * 2. Provide your own frame buffer operations. 42 */ 43 struct fb_info info; 44 45 /* Here starts the frame buffer device dependent part */ 46 /* You can use this to store e.g. the board number if you support */ 47 /* multiple boards */ 48}; 49 50 51struct xxxfb_par { 52 /* 53 * The hardware specific data in this structure uniquely defines a video 54 * mode. 55 * 56 * If your hardware supports only one video mode, you can leave it empty. 57 */ 58}; 59 60 61 /* 62 * If your driver supports multiple boards, you should make these arrays, 63 * or allocate them dynamically (using kmalloc()). 64 */ 65 66static struct xxxfb_info fb_info; 67static struct xxxfb_par current_par; 68static int current_par_valid = 0; 69static struct display disp; 70 71static struct fb_var_screeninfo default_var; 72 73static int currcon = 0; 74static int inverse = 0; 75 76int xxxfb_init(void); 77int xxxfb_setup(char*); 78 79/* ------------------- chipset specific functions -------------------------- */ 80 81 82static void xxx_detect(void) 83{ 84 /* 85 * This function should detect the current video mode settings and store 86 * it as the default video mode 87 */ 88 89 struct xxxfb_par par; 90 91 /* ... */ 92 xxx_get_par(&par); 93 xxx_encode_var(&default_var, &par); 94} 95 96static int xxx_encode_fix(struct fb_fix_screeninfo *fix, struct xxxfb_par *par, 97 const struct fb_info *info) 98{ 99 /* 100 * This function should fill in the 'fix' structure based on the values 101 * in the `par' structure. 102 */ 103 104 /* ... */ 105 return 0; 106} 107 108static int xxx_decode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par, 109 const struct fb_info *info) 110{ 111 /* 112 * Get the video params out of 'var'. If a value doesn't fit, round it up, 113 * if it's too big, return -EINVAL. 114 * 115 * Suggestion: Round up in the following order: bits_per_pixel, xres, 116 * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, 117 * bitfields, horizontal timing, vertical timing. 118 */ 119 120 /* ... */ 121 122 /* pixclock in picos, htotal in pixels, vtotal in scanlines */ 123 if (!fbmon_valid_timings(pixclock, htotal, vtotal, info)) 124 return -EINVAL; 125 126 return 0; 127} 128 129static int xxx_encode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par, 130 const struct fb_info *info) 131{ 132 /* 133 * Fill the 'var' structure based on the values in 'par' and maybe other 134 * values read out of the hardware. 135 */ 136 137 /* ... */ 138 return 0; 139} 140 141static void xxx_get_par(struct xxxfb_par *par, const struct fb_info *info) 142{ 143 /* 144 * Fill the hardware's 'par' structure. 145 */ 146 147 if (current_par_valid) 148 *par = current_par; 149 else { 150 /* ... */ 151 } 152} 153 154static void xxx_set_par(struct xxxfb_par *par, const struct fb_info *info) 155{ 156 /* 157 * Set the hardware according to 'par'. 158 */ 159 160 current_par = *par; 161 current_par_valid = 1; 162 /* ... */ 163} 164 165static int xxx_getcolreg(unsigned regno, unsigned *red, unsigned *green, 166 unsigned *blue, unsigned *transp, 167 const struct fb_info *info) 168{ 169 /* 170 * Read a single color register and split it into colors/transparent. 171 * The return values must have a 16 bit magnitude. 172 * Return != 0 for invalid regno. 173 */ 174 175 /* ... */ 176 return 0; 177} 178 179static int xxx_setcolreg(unsigned regno, unsigned red, unsigned green, 180 unsigned blue, unsigned transp, 181 const struct fb_info *info) 182{ 183 /* 184 * Set a single color register. The values supplied have a 16 bit 185 * magnitude. 186 * Return != 0 for invalid regno. 187 */ 188 189 if (regno < 16) { 190 /* 191 * Make the first 16 colors of the palette available to fbcon 192 */ 193 if (is_cfb15) /* RGB 555 */ 194 ...fbcon_cmap.cfb16[regno] = ((red & 0xf800) >> 1) | 195 ((green & 0xf800) >> 6) | 196 ((blue & 0xf800) >> 11); 197 if (is_cfb16) /* RGB 565 */ 198 ...fbcon_cmap.cfb16[regno] = (red & 0xf800) | 199 ((green & 0xfc00) >> 5) | 200 ((blue & 0xf800) >> 11); 201 if (is_cfb24) /* RGB 888 */ 202 ...fbcon_cmap.cfb24[regno] = ((red & 0xff00) << 8) | 203 (green & 0xff00) | 204 ((blue & 0xff00) >> 8); 205 if (is_cfb32) /* RGBA 8888 */ 206 ...fbcon_cmap.cfb32[regno] = ((red & 0xff00) << 16) | 207 ((green & 0xff00) << 8) | 208 (blue & 0xff00) | 209 ((transp & 0xff00) >> 8); 210 } 211 /* ... */ 212 return 0; 213} 214 215static int xxx_pan_display(struct fb_var_screeninfo *var, 216 struct xxxfb_par *par, const struct fb_info *info) 217{ 218 /* 219 * Pan (or wrap, depending on the `vmode' field) the display using the 220 * `xoffset' and `yoffset' fields of the `var' structure. 221 * If the values don't fit, return -EINVAL. 222 */ 223 224 /* ... */ 225 return 0; 226} 227 228static int xxx_blank(int blank_mode, const struct fb_info *info) 229{ 230 /* 231 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL 232 * then the caller blanks by setting the CLUT (Color Look Up Table) to all 233 * black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due 234 * to e.g. a video mode which doesn't support it. Implements VESA suspend 235 * and powerdown modes on hardware that supports disabling hsync/vsync: 236 * blank_mode == 2: suspend vsync 237 * blank_mode == 3: suspend hsync 238 * blank_mode == 4: powerdown 239 */ 240 241 /* ... */ 242 return 0; 243} 244 245static void xxx_set_disp(const void *par, struct display *disp, 246 struct fb_info_gen *info) 247{ 248 /* 249 * Fill in a pointer with the virtual address of the mapped frame buffer. 250 * Fill in a pointer to appropriate low level text console operations (and 251 * optionally a pointer to help data) for the video mode `par' of your 252 * video hardware. These can be generic software routines, or hardware 253 * accelerated routines specifically tailored for your hardware. 254 * If you don't have any appropriate operations, you must fill in a 255 * pointer to dummy operations, and there will be no text output. 256 */ 257 disp->screen_base = virtual_frame_buffer_address; 258#ifdef FBCON_HAS_CFB8 259 if (is_cfb8) { 260 disp->dispsw = fbcon_cfb8; 261 } else 262#endif 263#ifdef FBCON_HAS_CFB16 264 if (is_cfb16) { 265 disp->dispsw = fbcon_cfb16; 266 disp->dispsw_data = ...fbcon_cmap.cfb16; /* console palette */ 267 } else 268#endif 269#ifdef FBCON_HAS_CFB24 270 if (is_cfb24) { 271 disp->dispsw = fbcon_cfb24; 272 disp->dispsw_data = ...fbcon_cmap.cfb24; /* console palette */ 273 } else 274#endif 275#ifdef FBCON_HAS_CFB32 276 if (is_cfb32) { 277 disp->dispsw = fbcon_cfb32; 278 disp->dispsw_data = ...fbcon_cmap.cfb32; /* console palette */ 279 } else 280#endif 281 disp->dispsw = &fbcon_dummy; 282} 283 284 285/* ------------ Interfaces to hardware functions ------------ */ 286 287 288struct fbgen_hwswitch xxx_switch = { 289 xxx_detect, xxx_encode_fix, xxx_decode_var, xxx_encode_var, xxx_get_par, 290 xxx_set_par, xxx_getcolreg, xxx_setcolreg, xxx_pan_display, xxx_blank, 291 xxx_set_disp 292}; 293 294 295 296/* ------------ Hardware Independent Functions ------------ */ 297 298 299 /* 300 * Initialization 301 */ 302 303int __init xxxfb_init(void) 304{ 305 fb_info.gen.fbhw = &xxx_switch; 306 fb_info.gen.fbhw->detect(); 307 strcpy(fb_info.gen.info.modename, "XXX"); 308 fb_info.gen.info.changevar = NULL; 309 fb_info.gen.info.node = -1; 310 fb_info.gen.info.fbops = &xxxfb_ops; 311 fb_info.gen.info.disp = &disp; 312 fb_info.gen.info.switch_con = &xxxfb_switch; 313 fb_info.gen.info.updatevar = &xxxfb_update_var; 314 fb_info.gen.info.blank = &xxxfb_blank; 315 fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT; 316 /* This should give a reasonable default video mode */ 317 fbgen_get_var(&disp.var, -1, &fb_info.gen.info); 318 fbgen_do_set_var(&disp.var, 1, &fb_info.gen); 319 fbgen_set_disp(-1, &fb_info.gen); 320 fbgen_install_cmap(0, &fb_info.gen); 321 if (register_framebuffer(&fb_info.gen.info) < 0) 322 return -EINVAL; 323 printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node), 324 fb_info.gen.info.modename); 325 326 /* uncomment this if your driver cannot be unloaded */ 327 /* MOD_INC_USE_COUNT; */ 328 return 0; 329} 330 331 332 /* 333 * Cleanup 334 */ 335 336void xxxfb_cleanup(struct fb_info *info) 337{ 338 /* 339 * If your driver supports multiple boards, you should unregister and 340 * clean up all instances. 341 */ 342 343 unregister_framebuffer(info); 344 /* ... */ 345} 346 347 348 /* 349 * Setup 350 */ 351 352int __init xxxfb_setup(char *options) 353{ 354 /* Parse user speficied options (`video=xxxfb:') */ 355} 356 357 358/* ------------------------------------------------------------------------- */ 359 360 361 /* 362 * Frame buffer operations 363 */ 364 365/* If all you need is that - just don't define ->fb_open */ 366static int xxxfb_open(const struct fb_info *info, int user) 367{ 368 return 0; 369} 370 371/* If all you need is that - just don't define ->fb_release */ 372static int xxxfb_release(const struct fb_info *info, int user) 373{ 374 return 0; 375} 376 377 378 /* 379 * In most cases the `generic' routines (fbgen_*) should be satisfactory. 380 * However, you're free to fill in your own replacements. 381 */ 382 383static struct fb_ops xxxfb_ops = { 384 owner: THIS_MODULE, 385 fb_open: xxxfb_open, /* only if you need it to do something */ 386 fb_release: xxxfb_release, /* only if you need it to do something */ 387 fb_get_fix: fbgen_get_fix, 388 fb_get_var: fbgen_get_var, 389 fb_set_var: fbgen_set_var, 390 fb_get_cmap: fbgen_get_cmap, 391 fb_set_cmap: fbgen_set_cmap, 392 fb_pan_display: fbgen_pan_display, 393 fb_ioctl: xxxfb_ioctl, /* optional */ 394}; 395 396 397/* ------------------------------------------------------------------------- */ 398 399 400 /* 401 * Modularization 402 */ 403 404#ifdef MODULE 405MODULE_LICENSE("GPL"); 406int init_module(void) 407{ 408 return xxxfb_init(); 409} 410 411void cleanup_module(void) 412{ 413 xxxfb_cleanup(void); 414} 415#endif /* MODULE */ 416