18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Modified to new api Jan 2001 by James Simmons (jsimmons@transvirtual.com) 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Created 28 Dec 1997 by Geert Uytterhoeven 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * I have started rewriting this driver as a example of the upcoming new API 108c2ecf20Sopenharmony_ci * The primary goal is to remove the console code from fbdev and place it 118c2ecf20Sopenharmony_ci * into fbcon.c. This reduces the code and makes writing a new fbdev driver 128c2ecf20Sopenharmony_ci * easy since the author doesn't need to worry about console internals. It 138c2ecf20Sopenharmony_ci * also allows the ability to run fbdev without a console/tty system on top 148c2ecf20Sopenharmony_ci * of it. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * First the roles of struct fb_info and struct display have changed. Struct 178c2ecf20Sopenharmony_ci * display will go away. The way the new framebuffer console code will 188c2ecf20Sopenharmony_ci * work is that it will act to translate data about the tty/console in 198c2ecf20Sopenharmony_ci * struct vc_data to data in a device independent way in struct fb_info. Then 208c2ecf20Sopenharmony_ci * various functions in struct fb_ops will be called to store the device 218c2ecf20Sopenharmony_ci * dependent state in the par field in struct fb_info and to change the 228c2ecf20Sopenharmony_ci * hardware to that state. This allows a very clean separation of the fbdev 238c2ecf20Sopenharmony_ci * layer from the console layer. It also allows one to use fbdev on its own 248c2ecf20Sopenharmony_ci * which is a bounus for embedded devices. The reason this approach works is 258c2ecf20Sopenharmony_ci * for each framebuffer device when used as a tty/console device is allocated 268c2ecf20Sopenharmony_ci * a set of virtual terminals to it. Only one virtual terminal can be active 278c2ecf20Sopenharmony_ci * per framebuffer device. We already have all the data we need in struct 288c2ecf20Sopenharmony_ci * vc_data so why store a bunch of colormaps and other fbdev specific data 298c2ecf20Sopenharmony_ci * per virtual terminal. 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * As you can see doing this makes the con parameter pretty much useless 328c2ecf20Sopenharmony_ci * for struct fb_ops functions, as it should be. Also having struct 338c2ecf20Sopenharmony_ci * fb_var_screeninfo and other data in fb_info pretty much eliminates the 348c2ecf20Sopenharmony_ci * need for get_fix and get_var. Once all drivers use the fix, var, and cmap 358c2ecf20Sopenharmony_ci * fbcon can be written around these fields. This will also eliminate the 368c2ecf20Sopenharmony_ci * need to regenerate struct fb_var_screeninfo, struct fb_fix_screeninfo 378c2ecf20Sopenharmony_ci * struct fb_cmap every time get_var, get_fix, get_cmap functions are called 388c2ecf20Sopenharmony_ci * as many drivers do now. 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 418c2ecf20Sopenharmony_ci * License. See the file COPYING in the main directory of this archive for 428c2ecf20Sopenharmony_ci * more details. 438c2ecf20Sopenharmony_ci */ 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#include <linux/module.h> 468c2ecf20Sopenharmony_ci#include <linux/kernel.h> 478c2ecf20Sopenharmony_ci#include <linux/errno.h> 488c2ecf20Sopenharmony_ci#include <linux/string.h> 498c2ecf20Sopenharmony_ci#include <linux/mm.h> 508c2ecf20Sopenharmony_ci#include <linux/slab.h> 518c2ecf20Sopenharmony_ci#include <linux/delay.h> 528c2ecf20Sopenharmony_ci#include <linux/fb.h> 538c2ecf20Sopenharmony_ci#include <linux/init.h> 548c2ecf20Sopenharmony_ci#include <linux/pci.h> 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci /* 578c2ecf20Sopenharmony_ci * This is just simple sample code. 588c2ecf20Sopenharmony_ci * 598c2ecf20Sopenharmony_ci * No warranty that it actually compiles. 608c2ecf20Sopenharmony_ci * Even less warranty that it actually works :-) 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* 648c2ecf20Sopenharmony_ci * Driver data 658c2ecf20Sopenharmony_ci */ 668c2ecf20Sopenharmony_cistatic char *mode_option; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* 698c2ecf20Sopenharmony_ci * If your driver supports multiple boards, you should make the 708c2ecf20Sopenharmony_ci * below data types arrays, or allocate them dynamically (using kmalloc()). 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/* 748c2ecf20Sopenharmony_ci * This structure defines the hardware state of the graphics card. Normally 758c2ecf20Sopenharmony_ci * you place this in a header file in linux/include/video. This file usually 768c2ecf20Sopenharmony_ci * also includes register information. That allows other driver subsystems 778c2ecf20Sopenharmony_ci * and userland applications the ability to use the same header file to 788c2ecf20Sopenharmony_ci * avoid duplicate work and easy porting of software. 798c2ecf20Sopenharmony_ci */ 808c2ecf20Sopenharmony_cistruct xxx_par; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/* 838c2ecf20Sopenharmony_ci * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo 848c2ecf20Sopenharmony_ci * if we don't use modedb. If we do use modedb see xxxfb_init how to use it 858c2ecf20Sopenharmony_ci * to get a fb_var_screeninfo. Otherwise define a default var as well. 868c2ecf20Sopenharmony_ci */ 878c2ecf20Sopenharmony_cistatic const struct fb_fix_screeninfo xxxfb_fix = { 888c2ecf20Sopenharmony_ci .id = "FB's name", 898c2ecf20Sopenharmony_ci .type = FB_TYPE_PACKED_PIXELS, 908c2ecf20Sopenharmony_ci .visual = FB_VISUAL_PSEUDOCOLOR, 918c2ecf20Sopenharmony_ci .xpanstep = 1, 928c2ecf20Sopenharmony_ci .ypanstep = 1, 938c2ecf20Sopenharmony_ci .ywrapstep = 1, 948c2ecf20Sopenharmony_ci .accel = FB_ACCEL_NONE, 958c2ecf20Sopenharmony_ci}; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci /* 988c2ecf20Sopenharmony_ci * Modern graphical hardware not only supports pipelines but some 998c2ecf20Sopenharmony_ci * also support multiple monitors where each display can have its 1008c2ecf20Sopenharmony_ci * its own unique data. In this case each display could be 1018c2ecf20Sopenharmony_ci * represented by a separate framebuffer device thus a separate 1028c2ecf20Sopenharmony_ci * struct fb_info. Now the struct xxx_par represents the graphics 1038c2ecf20Sopenharmony_ci * hardware state thus only one exist per card. In this case the 1048c2ecf20Sopenharmony_ci * struct xxx_par for each graphics card would be shared between 1058c2ecf20Sopenharmony_ci * every struct fb_info that represents a framebuffer on that card. 1068c2ecf20Sopenharmony_ci * This allows when one display changes it video resolution (info->var) 1078c2ecf20Sopenharmony_ci * the other displays know instantly. Each display can always be 1088c2ecf20Sopenharmony_ci * aware of the entire hardware state that affects it because they share 1098c2ecf20Sopenharmony_ci * the same xxx_par struct. The other side of the coin is multiple 1108c2ecf20Sopenharmony_ci * graphics cards that pass data around until it is finally displayed 1118c2ecf20Sopenharmony_ci * on one monitor. Such examples are the voodoo 1 cards and high end 1128c2ecf20Sopenharmony_ci * NUMA graphics servers. For this case we have a bunch of pars, each 1138c2ecf20Sopenharmony_ci * one that represents a graphics state, that belong to one struct 1148c2ecf20Sopenharmony_ci * fb_info. Their you would want to have *par point to a array of device 1158c2ecf20Sopenharmony_ci * states and have each struct fb_ops function deal with all those 1168c2ecf20Sopenharmony_ci * states. I hope this covers every possible hardware design. If not 1178c2ecf20Sopenharmony_ci * feel free to send your ideas at jsimmons@users.sf.net 1188c2ecf20Sopenharmony_ci */ 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci /* 1218c2ecf20Sopenharmony_ci * If your driver supports multiple boards or it supports multiple 1228c2ecf20Sopenharmony_ci * framebuffers, you should make these arrays, or allocate them 1238c2ecf20Sopenharmony_ci * dynamically using framebuffer_alloc() and free them with 1248c2ecf20Sopenharmony_ci * framebuffer_release(). 1258c2ecf20Sopenharmony_ci */ 1268c2ecf20Sopenharmony_cistatic struct fb_info info; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci /* 1298c2ecf20Sopenharmony_ci * Each one represents the state of the hardware. Most hardware have 1308c2ecf20Sopenharmony_ci * just one hardware state. These here represent the default state(s). 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_cistatic struct xxx_par __initdata current_par; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ciint xxxfb_init(void); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci/** 1378c2ecf20Sopenharmony_ci * xxxfb_open - Optional function. Called when the framebuffer is 1388c2ecf20Sopenharmony_ci * first accessed. 1398c2ecf20Sopenharmony_ci * @info: frame buffer structure that represents a single frame buffer 1408c2ecf20Sopenharmony_ci * @user: tell us if the userland (value=1) or the console is accessing 1418c2ecf20Sopenharmony_ci * the framebuffer. 1428c2ecf20Sopenharmony_ci * 1438c2ecf20Sopenharmony_ci * This function is the first function called in the framebuffer api. 1448c2ecf20Sopenharmony_ci * Usually you don't need to provide this function. The case where it 1458c2ecf20Sopenharmony_ci * is used is to change from a text mode hardware state to a graphics 1468c2ecf20Sopenharmony_ci * mode state. 1478c2ecf20Sopenharmony_ci * 1488c2ecf20Sopenharmony_ci * Returns negative errno on error, or zero on success. 1498c2ecf20Sopenharmony_ci */ 1508c2ecf20Sopenharmony_cistatic int xxxfb_open(struct fb_info *info, int user) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci return 0; 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci/** 1568c2ecf20Sopenharmony_ci * xxxfb_release - Optional function. Called when the framebuffer 1578c2ecf20Sopenharmony_ci * device is closed. 1588c2ecf20Sopenharmony_ci * @info: frame buffer structure that represents a single frame buffer 1598c2ecf20Sopenharmony_ci * @user: tell us if the userland (value=1) or the console is accessing 1608c2ecf20Sopenharmony_ci * the framebuffer. 1618c2ecf20Sopenharmony_ci * 1628c2ecf20Sopenharmony_ci * Thus function is called when we close /dev/fb or the framebuffer 1638c2ecf20Sopenharmony_ci * console system is released. Usually you don't need this function. 1648c2ecf20Sopenharmony_ci * The case where it is usually used is to go from a graphics state 1658c2ecf20Sopenharmony_ci * to a text mode state. 1668c2ecf20Sopenharmony_ci * 1678c2ecf20Sopenharmony_ci * Returns negative errno on error, or zero on success. 1688c2ecf20Sopenharmony_ci */ 1698c2ecf20Sopenharmony_cistatic int xxxfb_release(struct fb_info *info, int user) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci return 0; 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci/** 1758c2ecf20Sopenharmony_ci * xxxfb_check_var - Optional function. Validates a var passed in. 1768c2ecf20Sopenharmony_ci * @var: frame buffer variable screen structure 1778c2ecf20Sopenharmony_ci * @info: frame buffer structure that represents a single frame buffer 1788c2ecf20Sopenharmony_ci * 1798c2ecf20Sopenharmony_ci * Checks to see if the hardware supports the state requested by 1808c2ecf20Sopenharmony_ci * var passed in. This function does not alter the hardware state!!! 1818c2ecf20Sopenharmony_ci * This means the data stored in struct fb_info and struct xxx_par do 1828c2ecf20Sopenharmony_ci * not change. This includes the var inside of struct fb_info. 1838c2ecf20Sopenharmony_ci * Do NOT change these. This function can be called on its own if we 1848c2ecf20Sopenharmony_ci * intent to only test a mode and not actually set it. The stuff in 1858c2ecf20Sopenharmony_ci * modedb.c is a example of this. If the var passed in is slightly 1868c2ecf20Sopenharmony_ci * off by what the hardware can support then we alter the var PASSED in 1878c2ecf20Sopenharmony_ci * to what we can do. 1888c2ecf20Sopenharmony_ci * 1898c2ecf20Sopenharmony_ci * For values that are off, this function must round them _up_ to the 1908c2ecf20Sopenharmony_ci * next value that is supported by the hardware. If the value is 1918c2ecf20Sopenharmony_ci * greater than the highest value supported by the hardware, then this 1928c2ecf20Sopenharmony_ci * function must return -EINVAL. 1938c2ecf20Sopenharmony_ci * 1948c2ecf20Sopenharmony_ci * Exception to the above rule: Some drivers have a fixed mode, ie, 1958c2ecf20Sopenharmony_ci * the hardware is already set at boot up, and cannot be changed. In 1968c2ecf20Sopenharmony_ci * this case, it is more acceptable that this function just return 1978c2ecf20Sopenharmony_ci * a copy of the currently working var (info->var). Better is to not 1988c2ecf20Sopenharmony_ci * implement this function, as the upper layer will do the copying 1998c2ecf20Sopenharmony_ci * of the current var for you. 2008c2ecf20Sopenharmony_ci * 2018c2ecf20Sopenharmony_ci * Note: This is the only function where the contents of var can be 2028c2ecf20Sopenharmony_ci * freely adjusted after the driver has been registered. If you find 2038c2ecf20Sopenharmony_ci * that you have code outside of this function that alters the content 2048c2ecf20Sopenharmony_ci * of var, then you are doing something wrong. Note also that the 2058c2ecf20Sopenharmony_ci * contents of info->var must be left untouched at all times after 2068c2ecf20Sopenharmony_ci * driver registration. 2078c2ecf20Sopenharmony_ci * 2088c2ecf20Sopenharmony_ci * Returns negative errno on error, or zero on success. 2098c2ecf20Sopenharmony_ci */ 2108c2ecf20Sopenharmony_cistatic int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci /* ... */ 2138c2ecf20Sopenharmony_ci return 0; 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci/** 2178c2ecf20Sopenharmony_ci * xxxfb_set_par - Optional function. Alters the hardware state. 2188c2ecf20Sopenharmony_ci * @info: frame buffer structure that represents a single frame buffer 2198c2ecf20Sopenharmony_ci * 2208c2ecf20Sopenharmony_ci * Using the fb_var_screeninfo in fb_info we set the resolution of the 2218c2ecf20Sopenharmony_ci * this particular framebuffer. This function alters the par AND the 2228c2ecf20Sopenharmony_ci * fb_fix_screeninfo stored in fb_info. It doesn't not alter var in 2238c2ecf20Sopenharmony_ci * fb_info since we are using that data. This means we depend on the 2248c2ecf20Sopenharmony_ci * data in var inside fb_info to be supported by the hardware. 2258c2ecf20Sopenharmony_ci * 2268c2ecf20Sopenharmony_ci * This function is also used to recover/restore the hardware to a 2278c2ecf20Sopenharmony_ci * known working state. 2288c2ecf20Sopenharmony_ci * 2298c2ecf20Sopenharmony_ci * xxxfb_check_var is always called before xxxfb_set_par to ensure that 2308c2ecf20Sopenharmony_ci * the contents of var is always valid. 2318c2ecf20Sopenharmony_ci * 2328c2ecf20Sopenharmony_ci * Again if you can't change the resolution you don't need this function. 2338c2ecf20Sopenharmony_ci * 2348c2ecf20Sopenharmony_ci * However, even if your hardware does not support mode changing, 2358c2ecf20Sopenharmony_ci * a set_par might be needed to at least initialize the hardware to 2368c2ecf20Sopenharmony_ci * a known working state, especially if it came back from another 2378c2ecf20Sopenharmony_ci * process that also modifies the same hardware, such as X. 2388c2ecf20Sopenharmony_ci * 2398c2ecf20Sopenharmony_ci * If this is the case, a combination such as the following should work: 2408c2ecf20Sopenharmony_ci * 2418c2ecf20Sopenharmony_ci * static int xxxfb_check_var(struct fb_var_screeninfo *var, 2428c2ecf20Sopenharmony_ci * struct fb_info *info) 2438c2ecf20Sopenharmony_ci * { 2448c2ecf20Sopenharmony_ci * *var = info->var; 2458c2ecf20Sopenharmony_ci * return 0; 2468c2ecf20Sopenharmony_ci * } 2478c2ecf20Sopenharmony_ci * 2488c2ecf20Sopenharmony_ci * static int xxxfb_set_par(struct fb_info *info) 2498c2ecf20Sopenharmony_ci * { 2508c2ecf20Sopenharmony_ci * init your hardware here 2518c2ecf20Sopenharmony_ci * } 2528c2ecf20Sopenharmony_ci * 2538c2ecf20Sopenharmony_ci * Returns negative errno on error, or zero on success. 2548c2ecf20Sopenharmony_ci */ 2558c2ecf20Sopenharmony_cistatic int xxxfb_set_par(struct fb_info *info) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci struct xxx_par *par = info->par; 2588c2ecf20Sopenharmony_ci /* ... */ 2598c2ecf20Sopenharmony_ci return 0; 2608c2ecf20Sopenharmony_ci} 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci/** 2638c2ecf20Sopenharmony_ci * xxxfb_setcolreg - Optional function. Sets a color register. 2648c2ecf20Sopenharmony_ci * @regno: Which register in the CLUT we are programming 2658c2ecf20Sopenharmony_ci * @red: The red value which can be up to 16 bits wide 2668c2ecf20Sopenharmony_ci * @green: The green value which can be up to 16 bits wide 2678c2ecf20Sopenharmony_ci * @blue: The blue value which can be up to 16 bits wide. 2688c2ecf20Sopenharmony_ci * @transp: If supported, the alpha value which can be up to 16 bits wide. 2698c2ecf20Sopenharmony_ci * @info: frame buffer info structure 2708c2ecf20Sopenharmony_ci * 2718c2ecf20Sopenharmony_ci * Set a single color register. The values supplied have a 16 bit 2728c2ecf20Sopenharmony_ci * magnitude which needs to be scaled in this function for the hardware. 2738c2ecf20Sopenharmony_ci * Things to take into consideration are how many color registers, if 2748c2ecf20Sopenharmony_ci * any, are supported with the current color visual. With truecolor mode 2758c2ecf20Sopenharmony_ci * no color palettes are supported. Here a pseudo palette is created 2768c2ecf20Sopenharmony_ci * which we store the value in pseudo_palette in struct fb_info. For 2778c2ecf20Sopenharmony_ci * pseudocolor mode we have a limited color palette. To deal with this 2788c2ecf20Sopenharmony_ci * we can program what color is displayed for a particular pixel value. 2798c2ecf20Sopenharmony_ci * DirectColor is similar in that we can program each color field. If 2808c2ecf20Sopenharmony_ci * we have a static colormap we don't need to implement this function. 2818c2ecf20Sopenharmony_ci * 2828c2ecf20Sopenharmony_ci * Returns negative errno on error, or zero on success. 2838c2ecf20Sopenharmony_ci */ 2848c2ecf20Sopenharmony_cistatic int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green, 2858c2ecf20Sopenharmony_ci unsigned blue, unsigned transp, 2868c2ecf20Sopenharmony_ci struct fb_info *info) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci if (regno >= 256) /* no. of hw registers */ 2898c2ecf20Sopenharmony_ci return -EINVAL; 2908c2ecf20Sopenharmony_ci /* 2918c2ecf20Sopenharmony_ci * Program hardware... do anything you want with transp 2928c2ecf20Sopenharmony_ci */ 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* grayscale works only partially under directcolor */ 2958c2ecf20Sopenharmony_ci if (info->var.grayscale) { 2968c2ecf20Sopenharmony_ci /* grayscale = 0.30*R + 0.59*G + 0.11*B */ 2978c2ecf20Sopenharmony_ci red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci /* Directcolor: 3018c2ecf20Sopenharmony_ci * var->{color}.offset contains start of bitfield 3028c2ecf20Sopenharmony_ci * var->{color}.length contains length of bitfield 3038c2ecf20Sopenharmony_ci * {hardwarespecific} contains width of DAC 3048c2ecf20Sopenharmony_ci * pseudo_palette[X] is programmed to (X << red.offset) | 3058c2ecf20Sopenharmony_ci * (X << green.offset) | 3068c2ecf20Sopenharmony_ci * (X << blue.offset) 3078c2ecf20Sopenharmony_ci * RAMDAC[X] is programmed to (red, green, blue) 3088c2ecf20Sopenharmony_ci * color depth = SUM(var->{color}.length) 3098c2ecf20Sopenharmony_ci * 3108c2ecf20Sopenharmony_ci * Pseudocolor: 3118c2ecf20Sopenharmony_ci * var->{color}.offset is 0 unless the palette index takes less than 3128c2ecf20Sopenharmony_ci * bits_per_pixel bits and is stored in the upper 3138c2ecf20Sopenharmony_ci * bits of the pixel value 3148c2ecf20Sopenharmony_ci * var->{color}.length is set so that 1 << length is the number of 3158c2ecf20Sopenharmony_ci * available palette entries 3168c2ecf20Sopenharmony_ci * pseudo_palette is not used 3178c2ecf20Sopenharmony_ci * RAMDAC[X] is programmed to (red, green, blue) 3188c2ecf20Sopenharmony_ci * color depth = var->{color}.length 3198c2ecf20Sopenharmony_ci * 3208c2ecf20Sopenharmony_ci * Static pseudocolor: 3218c2ecf20Sopenharmony_ci * same as Pseudocolor, but the RAMDAC is not programmed (read-only) 3228c2ecf20Sopenharmony_ci * 3238c2ecf20Sopenharmony_ci * Mono01/Mono10: 3248c2ecf20Sopenharmony_ci * Has only 2 values, black on white or white on black (fg on bg), 3258c2ecf20Sopenharmony_ci * var->{color}.offset is 0 3268c2ecf20Sopenharmony_ci * white = (1 << var->{color}.length) - 1, black = 0 3278c2ecf20Sopenharmony_ci * pseudo_palette is not used 3288c2ecf20Sopenharmony_ci * RAMDAC does not exist 3298c2ecf20Sopenharmony_ci * color depth is always 2 3308c2ecf20Sopenharmony_ci * 3318c2ecf20Sopenharmony_ci * Truecolor: 3328c2ecf20Sopenharmony_ci * does not use RAMDAC (usually has 3 of them). 3338c2ecf20Sopenharmony_ci * var->{color}.offset contains start of bitfield 3348c2ecf20Sopenharmony_ci * var->{color}.length contains length of bitfield 3358c2ecf20Sopenharmony_ci * pseudo_palette is programmed to (red << red.offset) | 3368c2ecf20Sopenharmony_ci * (green << green.offset) | 3378c2ecf20Sopenharmony_ci * (blue << blue.offset) | 3388c2ecf20Sopenharmony_ci * (transp << transp.offset) 3398c2ecf20Sopenharmony_ci * RAMDAC does not exist 3408c2ecf20Sopenharmony_ci * color depth = SUM(var->{color}.length}) 3418c2ecf20Sopenharmony_ci * 3428c2ecf20Sopenharmony_ci * The color depth is used by fbcon for choosing the logo and also 3438c2ecf20Sopenharmony_ci * for color palette transformation if color depth < 4 3448c2ecf20Sopenharmony_ci * 3458c2ecf20Sopenharmony_ci * As can be seen from the above, the field bits_per_pixel is _NOT_ 3468c2ecf20Sopenharmony_ci * a criteria for describing the color visual. 3478c2ecf20Sopenharmony_ci * 3488c2ecf20Sopenharmony_ci * A common mistake is assuming that bits_per_pixel <= 8 is pseudocolor, 3498c2ecf20Sopenharmony_ci * and higher than that, true/directcolor. This is incorrect, one needs 3508c2ecf20Sopenharmony_ci * to look at the fix->visual. 3518c2ecf20Sopenharmony_ci * 3528c2ecf20Sopenharmony_ci * Another common mistake is using bits_per_pixel to calculate the color 3538c2ecf20Sopenharmony_ci * depth. The bits_per_pixel field does not directly translate to color 3548c2ecf20Sopenharmony_ci * depth. You have to compute for the color depth (using the color 3558c2ecf20Sopenharmony_ci * bitfields) and fix->visual as seen above. 3568c2ecf20Sopenharmony_ci */ 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci /* 3598c2ecf20Sopenharmony_ci * This is the point where the color is converted to something that 3608c2ecf20Sopenharmony_ci * is acceptable by the hardware. 3618c2ecf20Sopenharmony_ci */ 3628c2ecf20Sopenharmony_ci#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) 3638c2ecf20Sopenharmony_ci red = CNVT_TOHW(red, info->var.red.length); 3648c2ecf20Sopenharmony_ci green = CNVT_TOHW(green, info->var.green.length); 3658c2ecf20Sopenharmony_ci blue = CNVT_TOHW(blue, info->var.blue.length); 3668c2ecf20Sopenharmony_ci transp = CNVT_TOHW(transp, info->var.transp.length); 3678c2ecf20Sopenharmony_ci#undef CNVT_TOHW 3688c2ecf20Sopenharmony_ci /* 3698c2ecf20Sopenharmony_ci * This is the point where the function feeds the color to the hardware 3708c2ecf20Sopenharmony_ci * palette after converting the colors to something acceptable by 3718c2ecf20Sopenharmony_ci * the hardware. Note, only FB_VISUAL_DIRECTCOLOR and 3728c2ecf20Sopenharmony_ci * FB_VISUAL_PSEUDOCOLOR visuals need to write to the hardware palette. 3738c2ecf20Sopenharmony_ci * If you have code that writes to the hardware CLUT, and it's not 3748c2ecf20Sopenharmony_ci * any of the above visuals, then you are doing something wrong. 3758c2ecf20Sopenharmony_ci */ 3768c2ecf20Sopenharmony_ci if (info->fix.visual == FB_VISUAL_DIRECTCOLOR || 3778c2ecf20Sopenharmony_ci info->fix.visual == FB_VISUAL_TRUECOLOR) 3788c2ecf20Sopenharmony_ci write_{red|green|blue|transp}_to_clut(); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci /* This is the point were you need to fill up the contents of 3818c2ecf20Sopenharmony_ci * info->pseudo_palette. This structure is used _only_ by fbcon, thus 3828c2ecf20Sopenharmony_ci * it only contains 16 entries to match the number of colors supported 3838c2ecf20Sopenharmony_ci * by the console. The pseudo_palette is used only if the visual is 3848c2ecf20Sopenharmony_ci * in directcolor or truecolor mode. With other visuals, the 3858c2ecf20Sopenharmony_ci * pseudo_palette is not used. (This might change in the future.) 3868c2ecf20Sopenharmony_ci * 3878c2ecf20Sopenharmony_ci * The contents of the pseudo_palette is in raw pixel format. Ie, each 3888c2ecf20Sopenharmony_ci * entry can be written directly to the framebuffer without any conversion. 3898c2ecf20Sopenharmony_ci * The pseudo_palette is (void *). However, if using the generic 3908c2ecf20Sopenharmony_ci * drawing functions (cfb_imageblit, cfb_fillrect), the pseudo_palette 3918c2ecf20Sopenharmony_ci * must be casted to (u32 *) _regardless_ of the bits per pixel. If the 3928c2ecf20Sopenharmony_ci * driver is using its own drawing functions, then it can use whatever 3938c2ecf20Sopenharmony_ci * size it wants. 3948c2ecf20Sopenharmony_ci */ 3958c2ecf20Sopenharmony_ci if (info->fix.visual == FB_VISUAL_TRUECOLOR || 3968c2ecf20Sopenharmony_ci info->fix.visual == FB_VISUAL_DIRECTCOLOR) { 3978c2ecf20Sopenharmony_ci u32 v; 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci if (regno >= 16) 4008c2ecf20Sopenharmony_ci return -EINVAL; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci v = (red << info->var.red.offset) | 4038c2ecf20Sopenharmony_ci (green << info->var.green.offset) | 4048c2ecf20Sopenharmony_ci (blue << info->var.blue.offset) | 4058c2ecf20Sopenharmony_ci (transp << info->var.transp.offset); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci ((u32*)(info->pseudo_palette))[regno] = v; 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* ... */ 4118c2ecf20Sopenharmony_ci return 0; 4128c2ecf20Sopenharmony_ci} 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci/** 4158c2ecf20Sopenharmony_ci * xxxfb_pan_display - NOT a required function. Pans the display. 4168c2ecf20Sopenharmony_ci * @var: frame buffer variable screen structure 4178c2ecf20Sopenharmony_ci * @info: frame buffer structure that represents a single frame buffer 4188c2ecf20Sopenharmony_ci * 4198c2ecf20Sopenharmony_ci * Pan (or wrap, depending on the `vmode' field) the display using the 4208c2ecf20Sopenharmony_ci * `xoffset' and `yoffset' fields of the `var' structure. 4218c2ecf20Sopenharmony_ci * If the values don't fit, return -EINVAL. 4228c2ecf20Sopenharmony_ci * 4238c2ecf20Sopenharmony_ci * Returns negative errno on error, or zero on success. 4248c2ecf20Sopenharmony_ci */ 4258c2ecf20Sopenharmony_cistatic int xxxfb_pan_display(struct fb_var_screeninfo *var, 4268c2ecf20Sopenharmony_ci struct fb_info *info) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci /* 4298c2ecf20Sopenharmony_ci * If your hardware does not support panning, _do_ _not_ implement this 4308c2ecf20Sopenharmony_ci * function. Creating a dummy function will just confuse user apps. 4318c2ecf20Sopenharmony_ci */ 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci /* 4348c2ecf20Sopenharmony_ci * Note that even if this function is fully functional, a setting of 4358c2ecf20Sopenharmony_ci * 0 in both xpanstep and ypanstep means that this function will never 4368c2ecf20Sopenharmony_ci * get called. 4378c2ecf20Sopenharmony_ci */ 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci /* ... */ 4408c2ecf20Sopenharmony_ci return 0; 4418c2ecf20Sopenharmony_ci} 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci/** 4448c2ecf20Sopenharmony_ci * xxxfb_blank - NOT a required function. Blanks the display. 4458c2ecf20Sopenharmony_ci * @blank_mode: the blank mode we want. 4468c2ecf20Sopenharmony_ci * @info: frame buffer structure that represents a single frame buffer 4478c2ecf20Sopenharmony_ci * 4488c2ecf20Sopenharmony_ci * Blank the screen if blank_mode != FB_BLANK_UNBLANK, else unblank. 4498c2ecf20Sopenharmony_ci * Return 0 if blanking succeeded, != 0 if un-/blanking failed due to 4508c2ecf20Sopenharmony_ci * e.g. a video mode which doesn't support it. 4518c2ecf20Sopenharmony_ci * 4528c2ecf20Sopenharmony_ci * Implements VESA suspend and powerdown modes on hardware that supports 4538c2ecf20Sopenharmony_ci * disabling hsync/vsync: 4548c2ecf20Sopenharmony_ci * 4558c2ecf20Sopenharmony_ci * FB_BLANK_NORMAL = display is blanked, syncs are on. 4568c2ecf20Sopenharmony_ci * FB_BLANK_HSYNC_SUSPEND = hsync off 4578c2ecf20Sopenharmony_ci * FB_BLANK_VSYNC_SUSPEND = vsync off 4588c2ecf20Sopenharmony_ci * FB_BLANK_POWERDOWN = hsync and vsync off 4598c2ecf20Sopenharmony_ci * 4608c2ecf20Sopenharmony_ci * If implementing this function, at least support FB_BLANK_UNBLANK. 4618c2ecf20Sopenharmony_ci * Return !0 for any modes that are unimplemented. 4628c2ecf20Sopenharmony_ci * 4638c2ecf20Sopenharmony_ci */ 4648c2ecf20Sopenharmony_cistatic int xxxfb_blank(int blank_mode, struct fb_info *info) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci /* ... */ 4678c2ecf20Sopenharmony_ci return 0; 4688c2ecf20Sopenharmony_ci} 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci/* ------------ Accelerated Functions --------------------- */ 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci/* 4738c2ecf20Sopenharmony_ci * We provide our own functions if we have hardware acceleration 4748c2ecf20Sopenharmony_ci * or non packed pixel format layouts. If we have no hardware 4758c2ecf20Sopenharmony_ci * acceleration, we can use a generic unaccelerated function. If using 4768c2ecf20Sopenharmony_ci * a pack pixel format just use the functions in cfb_*.c. Each file 4778c2ecf20Sopenharmony_ci * has one of the three different accel functions we support. 4788c2ecf20Sopenharmony_ci */ 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci/** 4818c2ecf20Sopenharmony_ci * xxxfb_fillrect - REQUIRED function. Can use generic routines if 4828c2ecf20Sopenharmony_ci * non acclerated hardware and packed pixel based. 4838c2ecf20Sopenharmony_ci * Draws a rectangle on the screen. 4848c2ecf20Sopenharmony_ci * 4858c2ecf20Sopenharmony_ci * @info: frame buffer structure that represents a single frame buffer 4868c2ecf20Sopenharmony_ci * @region: The structure representing the rectangular region we 4878c2ecf20Sopenharmony_ci * wish to draw to. 4888c2ecf20Sopenharmony_ci * 4898c2ecf20Sopenharmony_ci * This drawing operation places/removes a retangle on the screen 4908c2ecf20Sopenharmony_ci * depending on the rastering operation with the value of color which 4918c2ecf20Sopenharmony_ci * is in the current color depth format. 4928c2ecf20Sopenharmony_ci */ 4938c2ecf20Sopenharmony_civoid xxxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci/* Meaning of struct fb_fillrect 4968c2ecf20Sopenharmony_ci * 4978c2ecf20Sopenharmony_ci * @dx: The x and y corrdinates of the upper left hand corner of the 4988c2ecf20Sopenharmony_ci * @dy: area we want to draw to. 4998c2ecf20Sopenharmony_ci * @width: How wide the rectangle is we want to draw. 5008c2ecf20Sopenharmony_ci * @height: How tall the rectangle is we want to draw. 5018c2ecf20Sopenharmony_ci * @color: The color to fill in the rectangle with. 5028c2ecf20Sopenharmony_ci * @rop: The raster operation. We can draw the rectangle with a COPY 5038c2ecf20Sopenharmony_ci * of XOR which provides erasing effect. 5048c2ecf20Sopenharmony_ci */ 5058c2ecf20Sopenharmony_ci} 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci/** 5088c2ecf20Sopenharmony_ci * xxxfb_copyarea - REQUIRED function. Can use generic routines if 5098c2ecf20Sopenharmony_ci * non acclerated hardware and packed pixel based. 5108c2ecf20Sopenharmony_ci * Copies one area of the screen to another area. 5118c2ecf20Sopenharmony_ci * 5128c2ecf20Sopenharmony_ci * @info: frame buffer structure that represents a single frame buffer 5138c2ecf20Sopenharmony_ci * @area: Structure providing the data to copy the framebuffer contents 5148c2ecf20Sopenharmony_ci * from one region to another. 5158c2ecf20Sopenharmony_ci * 5168c2ecf20Sopenharmony_ci * This drawing operation copies a rectangular area from one area of the 5178c2ecf20Sopenharmony_ci * screen to another area. 5188c2ecf20Sopenharmony_ci */ 5198c2ecf20Sopenharmony_civoid xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) 5208c2ecf20Sopenharmony_ci{ 5218c2ecf20Sopenharmony_ci/* 5228c2ecf20Sopenharmony_ci * @dx: The x and y coordinates of the upper left hand corner of the 5238c2ecf20Sopenharmony_ci * @dy: destination area on the screen. 5248c2ecf20Sopenharmony_ci * @width: How wide the rectangle is we want to copy. 5258c2ecf20Sopenharmony_ci * @height: How tall the rectangle is we want to copy. 5268c2ecf20Sopenharmony_ci * @sx: The x and y coordinates of the upper left hand corner of the 5278c2ecf20Sopenharmony_ci * @sy: source area on the screen. 5288c2ecf20Sopenharmony_ci */ 5298c2ecf20Sopenharmony_ci} 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci/** 5338c2ecf20Sopenharmony_ci * xxxfb_imageblit - REQUIRED function. Can use generic routines if 5348c2ecf20Sopenharmony_ci * non acclerated hardware and packed pixel based. 5358c2ecf20Sopenharmony_ci * Copies a image from system memory to the screen. 5368c2ecf20Sopenharmony_ci * 5378c2ecf20Sopenharmony_ci * @info: frame buffer structure that represents a single frame buffer 5388c2ecf20Sopenharmony_ci * @image: structure defining the image. 5398c2ecf20Sopenharmony_ci * 5408c2ecf20Sopenharmony_ci * This drawing operation draws a image on the screen. It can be a 5418c2ecf20Sopenharmony_ci * mono image (needed for font handling) or a color image (needed for 5428c2ecf20Sopenharmony_ci * tux). 5438c2ecf20Sopenharmony_ci */ 5448c2ecf20Sopenharmony_civoid xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci/* 5478c2ecf20Sopenharmony_ci * @dx: The x and y coordinates of the upper left hand corner of the 5488c2ecf20Sopenharmony_ci * @dy: destination area to place the image on the screen. 5498c2ecf20Sopenharmony_ci * @width: How wide the image is we want to copy. 5508c2ecf20Sopenharmony_ci * @height: How tall the image is we want to copy. 5518c2ecf20Sopenharmony_ci * @fg_color: For mono bitmap images this is color data for 5528c2ecf20Sopenharmony_ci * @bg_color: the foreground and background of the image to 5538c2ecf20Sopenharmony_ci * write directly to the frmaebuffer. 5548c2ecf20Sopenharmony_ci * @depth: How many bits represent a single pixel for this image. 5558c2ecf20Sopenharmony_ci * @data: The actual data used to construct the image on the display. 5568c2ecf20Sopenharmony_ci * @cmap: The colormap used for color images. 5578c2ecf20Sopenharmony_ci */ 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci/* 5608c2ecf20Sopenharmony_ci * The generic function, cfb_imageblit, expects that the bitmap scanlines are 5618c2ecf20Sopenharmony_ci * padded to the next byte. Most hardware accelerators may require padding to 5628c2ecf20Sopenharmony_ci * the next u16 or the next u32. If that is the case, the driver can specify 5638c2ecf20Sopenharmony_ci * this by setting info->pixmap.scan_align = 2 or 4. See a more 5648c2ecf20Sopenharmony_ci * comprehensive description of the pixmap below. 5658c2ecf20Sopenharmony_ci */ 5668c2ecf20Sopenharmony_ci} 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci/** 5698c2ecf20Sopenharmony_ci * xxxfb_cursor - OPTIONAL. If your hardware lacks support 5708c2ecf20Sopenharmony_ci * for a cursor, leave this field NULL. 5718c2ecf20Sopenharmony_ci * 5728c2ecf20Sopenharmony_ci * @info: frame buffer structure that represents a single frame buffer 5738c2ecf20Sopenharmony_ci * @cursor: structure defining the cursor to draw. 5748c2ecf20Sopenharmony_ci * 5758c2ecf20Sopenharmony_ci * This operation is used to set or alter the properities of the 5768c2ecf20Sopenharmony_ci * cursor. 5778c2ecf20Sopenharmony_ci * 5788c2ecf20Sopenharmony_ci * Returns negative errno on error, or zero on success. 5798c2ecf20Sopenharmony_ci */ 5808c2ecf20Sopenharmony_ciint xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) 5818c2ecf20Sopenharmony_ci{ 5828c2ecf20Sopenharmony_ci/* 5838c2ecf20Sopenharmony_ci * @set: Which fields we are altering in struct fb_cursor 5848c2ecf20Sopenharmony_ci * @enable: Disable or enable the cursor 5858c2ecf20Sopenharmony_ci * @rop: The bit operation we want to do. 5868c2ecf20Sopenharmony_ci * @mask: This is the cursor mask bitmap. 5878c2ecf20Sopenharmony_ci * @dest: A image of the area we are going to display the cursor. 5888c2ecf20Sopenharmony_ci * Used internally by the driver. 5898c2ecf20Sopenharmony_ci * @hot: The hot spot. 5908c2ecf20Sopenharmony_ci * @image: The actual data for the cursor image. 5918c2ecf20Sopenharmony_ci * 5928c2ecf20Sopenharmony_ci * NOTES ON FLAGS (cursor->set): 5938c2ecf20Sopenharmony_ci * 5948c2ecf20Sopenharmony_ci * FB_CUR_SETIMAGE - the cursor image has changed (cursor->image.data) 5958c2ecf20Sopenharmony_ci * FB_CUR_SETPOS - the cursor position has changed (cursor->image.dx|dy) 5968c2ecf20Sopenharmony_ci * FB_CUR_SETHOT - the cursor hot spot has changed (cursor->hot.dx|dy) 5978c2ecf20Sopenharmony_ci * FB_CUR_SETCMAP - the cursor colors has changed (cursor->fg_color|bg_color) 5988c2ecf20Sopenharmony_ci * FB_CUR_SETSHAPE - the cursor bitmask has changed (cursor->mask) 5998c2ecf20Sopenharmony_ci * FB_CUR_SETSIZE - the cursor size has changed (cursor->width|height) 6008c2ecf20Sopenharmony_ci * FB_CUR_SETALL - everything has changed 6018c2ecf20Sopenharmony_ci * 6028c2ecf20Sopenharmony_ci * NOTES ON ROPs (cursor->rop, Raster Operation) 6038c2ecf20Sopenharmony_ci * 6048c2ecf20Sopenharmony_ci * ROP_XOR - cursor->image.data XOR cursor->mask 6058c2ecf20Sopenharmony_ci * ROP_COPY - curosr->image.data AND cursor->mask 6068c2ecf20Sopenharmony_ci * 6078c2ecf20Sopenharmony_ci * OTHER NOTES: 6088c2ecf20Sopenharmony_ci * 6098c2ecf20Sopenharmony_ci * - fbcon only supports a 2-color cursor (cursor->image.depth = 1) 6108c2ecf20Sopenharmony_ci * - The fb_cursor structure, @cursor, _will_ always contain valid 6118c2ecf20Sopenharmony_ci * fields, whether any particular bitfields in cursor->set is set 6128c2ecf20Sopenharmony_ci * or not. 6138c2ecf20Sopenharmony_ci */ 6148c2ecf20Sopenharmony_ci} 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci/** 6178c2ecf20Sopenharmony_ci * xxxfb_sync - NOT a required function. Normally the accel engine 6188c2ecf20Sopenharmony_ci * for a graphics card take a specific amount of time. 6198c2ecf20Sopenharmony_ci * Often we have to wait for the accelerator to finish 6208c2ecf20Sopenharmony_ci * its operation before we can write to the framebuffer 6218c2ecf20Sopenharmony_ci * so we can have consistent display output. 6228c2ecf20Sopenharmony_ci * 6238c2ecf20Sopenharmony_ci * @info: frame buffer structure that represents a single frame buffer 6248c2ecf20Sopenharmony_ci * 6258c2ecf20Sopenharmony_ci * If the driver has implemented its own hardware-based drawing function, 6268c2ecf20Sopenharmony_ci * implementing this function is highly recommended. 6278c2ecf20Sopenharmony_ci */ 6288c2ecf20Sopenharmony_ciint xxxfb_sync(struct fb_info *info) 6298c2ecf20Sopenharmony_ci{ 6308c2ecf20Sopenharmony_ci return 0; 6318c2ecf20Sopenharmony_ci} 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci /* 6348c2ecf20Sopenharmony_ci * Frame buffer operations 6358c2ecf20Sopenharmony_ci */ 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic const struct fb_ops xxxfb_ops = { 6388c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 6398c2ecf20Sopenharmony_ci .fb_open = xxxfb_open, 6408c2ecf20Sopenharmony_ci .fb_read = xxxfb_read, 6418c2ecf20Sopenharmony_ci .fb_write = xxxfb_write, 6428c2ecf20Sopenharmony_ci .fb_release = xxxfb_release, 6438c2ecf20Sopenharmony_ci .fb_check_var = xxxfb_check_var, 6448c2ecf20Sopenharmony_ci .fb_set_par = xxxfb_set_par, 6458c2ecf20Sopenharmony_ci .fb_setcolreg = xxxfb_setcolreg, 6468c2ecf20Sopenharmony_ci .fb_blank = xxxfb_blank, 6478c2ecf20Sopenharmony_ci .fb_pan_display = xxxfb_pan_display, 6488c2ecf20Sopenharmony_ci .fb_fillrect = xxxfb_fillrect, /* Needed !!! */ 6498c2ecf20Sopenharmony_ci .fb_copyarea = xxxfb_copyarea, /* Needed !!! */ 6508c2ecf20Sopenharmony_ci .fb_imageblit = xxxfb_imageblit, /* Needed !!! */ 6518c2ecf20Sopenharmony_ci .fb_cursor = xxxfb_cursor, /* Optional !!! */ 6528c2ecf20Sopenharmony_ci .fb_sync = xxxfb_sync, 6538c2ecf20Sopenharmony_ci .fb_ioctl = xxxfb_ioctl, 6548c2ecf20Sopenharmony_ci .fb_mmap = xxxfb_mmap, 6558c2ecf20Sopenharmony_ci}; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------- */ 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci /* 6608c2ecf20Sopenharmony_ci * Initialization 6618c2ecf20Sopenharmony_ci */ 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci/* static int __init xxfb_probe (struct platform_device *pdev) -- for platform devs */ 6648c2ecf20Sopenharmony_cistatic int xxxfb_probe(struct pci_dev *dev, const struct pci_device_id *ent) 6658c2ecf20Sopenharmony_ci{ 6668c2ecf20Sopenharmony_ci struct fb_info *info; 6678c2ecf20Sopenharmony_ci struct xxx_par *par; 6688c2ecf20Sopenharmony_ci struct device *device = &dev->dev; /* or &pdev->dev */ 6698c2ecf20Sopenharmony_ci int cmap_len, retval; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci /* 6728c2ecf20Sopenharmony_ci * Dynamically allocate info and par 6738c2ecf20Sopenharmony_ci */ 6748c2ecf20Sopenharmony_ci info = framebuffer_alloc(sizeof(struct xxx_par), device); 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci if (!info) { 6778c2ecf20Sopenharmony_ci /* goto error path */ 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci par = info->par; 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci /* 6838c2ecf20Sopenharmony_ci * Here we set the screen_base to the virtual memory address 6848c2ecf20Sopenharmony_ci * for the framebuffer. Usually we obtain the resource address 6858c2ecf20Sopenharmony_ci * from the bus layer and then translate it to virtual memory 6868c2ecf20Sopenharmony_ci * space via ioremap. Consult ioport.h. 6878c2ecf20Sopenharmony_ci */ 6888c2ecf20Sopenharmony_ci info->screen_base = framebuffer_virtual_memory; 6898c2ecf20Sopenharmony_ci info->fbops = &xxxfb_ops; 6908c2ecf20Sopenharmony_ci info->fix = xxxfb_fix; 6918c2ecf20Sopenharmony_ci info->pseudo_palette = pseudo_palette; /* The pseudopalette is an 6928c2ecf20Sopenharmony_ci * 16-member array 6938c2ecf20Sopenharmony_ci */ 6948c2ecf20Sopenharmony_ci /* 6958c2ecf20Sopenharmony_ci * Set up flags to indicate what sort of acceleration your 6968c2ecf20Sopenharmony_ci * driver can provide (pan/wrap/copyarea/etc.) and whether it 6978c2ecf20Sopenharmony_ci * is a module -- see FBINFO_* in include/linux/fb.h 6988c2ecf20Sopenharmony_ci * 6998c2ecf20Sopenharmony_ci * If your hardware can support any of the hardware accelerated functions 7008c2ecf20Sopenharmony_ci * fbcon performance will improve if info->flags is set properly. 7018c2ecf20Sopenharmony_ci * 7028c2ecf20Sopenharmony_ci * FBINFO_HWACCEL_COPYAREA - hardware moves 7038c2ecf20Sopenharmony_ci * FBINFO_HWACCEL_FILLRECT - hardware fills 7048c2ecf20Sopenharmony_ci * FBINFO_HWACCEL_IMAGEBLIT - hardware mono->color expansion 7058c2ecf20Sopenharmony_ci * FBINFO_HWACCEL_YPAN - hardware can pan display in y-axis 7068c2ecf20Sopenharmony_ci * FBINFO_HWACCEL_YWRAP - hardware can wrap display in y-axis 7078c2ecf20Sopenharmony_ci * FBINFO_HWACCEL_DISABLED - supports hardware accels, but disabled 7088c2ecf20Sopenharmony_ci * FBINFO_READS_FAST - if set, prefer moves over mono->color expansion 7098c2ecf20Sopenharmony_ci * FBINFO_MISC_TILEBLITTING - hardware can do tile blits 7108c2ecf20Sopenharmony_ci * 7118c2ecf20Sopenharmony_ci * NOTE: These are for fbcon use only. 7128c2ecf20Sopenharmony_ci */ 7138c2ecf20Sopenharmony_ci info->flags = FBINFO_DEFAULT; 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci/********************* This stage is optional ******************************/ 7168c2ecf20Sopenharmony_ci /* 7178c2ecf20Sopenharmony_ci * The struct pixmap is a scratch pad for the drawing functions. This 7188c2ecf20Sopenharmony_ci * is where the monochrome bitmap is constructed by the higher layers 7198c2ecf20Sopenharmony_ci * and then passed to the accelerator. For drivers that uses 7208c2ecf20Sopenharmony_ci * cfb_imageblit, you can skip this part. For those that have a more 7218c2ecf20Sopenharmony_ci * rigorous requirement, this stage is needed 7228c2ecf20Sopenharmony_ci */ 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci /* PIXMAP_SIZE should be small enough to optimize drawing, but not 7258c2ecf20Sopenharmony_ci * large enough that memory is wasted. A safe size is 7268c2ecf20Sopenharmony_ci * (max_xres * max_font_height/8). max_xres is driver dependent, 7278c2ecf20Sopenharmony_ci * max_font_height is 32. 7288c2ecf20Sopenharmony_ci */ 7298c2ecf20Sopenharmony_ci info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL); 7308c2ecf20Sopenharmony_ci if (!info->pixmap.addr) { 7318c2ecf20Sopenharmony_ci /* goto error */ 7328c2ecf20Sopenharmony_ci } 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci info->pixmap.size = PIXMAP_SIZE; 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci /* 7378c2ecf20Sopenharmony_ci * FB_PIXMAP_SYSTEM - memory is in system ram 7388c2ecf20Sopenharmony_ci * FB_PIXMAP_IO - memory is iomapped 7398c2ecf20Sopenharmony_ci * FB_PIXMAP_SYNC - if set, will call fb_sync() per access to pixmap, 7408c2ecf20Sopenharmony_ci * usually if FB_PIXMAP_IO is set. 7418c2ecf20Sopenharmony_ci * 7428c2ecf20Sopenharmony_ci * Currently, FB_PIXMAP_IO is unimplemented. 7438c2ecf20Sopenharmony_ci */ 7448c2ecf20Sopenharmony_ci info->pixmap.flags = FB_PIXMAP_SYSTEM; 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci /* 7478c2ecf20Sopenharmony_ci * scan_align is the number of padding for each scanline. It is in bytes. 7488c2ecf20Sopenharmony_ci * Thus for accelerators that need padding to the next u32, put 4 here. 7498c2ecf20Sopenharmony_ci */ 7508c2ecf20Sopenharmony_ci info->pixmap.scan_align = 4; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci /* 7538c2ecf20Sopenharmony_ci * buf_align is the amount to be padded for the buffer. For example, 7548c2ecf20Sopenharmony_ci * the i810fb needs a scan_align of 2 but expects it to be fed with 7558c2ecf20Sopenharmony_ci * dwords, so a buf_align = 4 is required. 7568c2ecf20Sopenharmony_ci */ 7578c2ecf20Sopenharmony_ci info->pixmap.buf_align = 4; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci /* access_align is how many bits can be accessed from the framebuffer 7608c2ecf20Sopenharmony_ci * ie. some epson cards allow 16-bit access only. Most drivers will 7618c2ecf20Sopenharmony_ci * be safe with u32 here. 7628c2ecf20Sopenharmony_ci * 7638c2ecf20Sopenharmony_ci * NOTE: This field is currently unused. 7648c2ecf20Sopenharmony_ci */ 7658c2ecf20Sopenharmony_ci info->pixmap.access_align = 32; 7668c2ecf20Sopenharmony_ci/***************************** End optional stage ***************************/ 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci /* 7698c2ecf20Sopenharmony_ci * This should give a reasonable default video mode. The following is 7708c2ecf20Sopenharmony_ci * done when we can set a video mode. 7718c2ecf20Sopenharmony_ci */ 7728c2ecf20Sopenharmony_ci if (!mode_option) 7738c2ecf20Sopenharmony_ci mode_option = "640x480@60"; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci if (!retval || retval == 4) 7788c2ecf20Sopenharmony_ci return -EINVAL; 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci /* This has to be done! */ 7818c2ecf20Sopenharmony_ci if (fb_alloc_cmap(&info->cmap, cmap_len, 0)) 7828c2ecf20Sopenharmony_ci return -ENOMEM; 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci /* 7858c2ecf20Sopenharmony_ci * The following is done in the case of having hardware with a static 7868c2ecf20Sopenharmony_ci * mode. If we are setting the mode ourselves we don't call this. 7878c2ecf20Sopenharmony_ci */ 7888c2ecf20Sopenharmony_ci info->var = xxxfb_var; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci /* 7918c2ecf20Sopenharmony_ci * For drivers that can... 7928c2ecf20Sopenharmony_ci */ 7938c2ecf20Sopenharmony_ci xxxfb_check_var(&info->var, info); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci /* 7968c2ecf20Sopenharmony_ci * Does a call to fb_set_par() before register_framebuffer needed? This 7978c2ecf20Sopenharmony_ci * will depend on you and the hardware. If you are sure that your driver 7988c2ecf20Sopenharmony_ci * is the only device in the system, a call to fb_set_par() is safe. 7998c2ecf20Sopenharmony_ci * 8008c2ecf20Sopenharmony_ci * Hardware in x86 systems has a VGA core. Calling set_par() at this 8018c2ecf20Sopenharmony_ci * point will corrupt the VGA console, so it might be safer to skip a 8028c2ecf20Sopenharmony_ci * call to set_par here and just allow fbcon to do it for you. 8038c2ecf20Sopenharmony_ci */ 8048c2ecf20Sopenharmony_ci /* xxxfb_set_par(info); */ 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci if (register_framebuffer(info) < 0) { 8078c2ecf20Sopenharmony_ci fb_dealloc_cmap(&info->cmap); 8088c2ecf20Sopenharmony_ci return -EINVAL; 8098c2ecf20Sopenharmony_ci } 8108c2ecf20Sopenharmony_ci fb_info(info, "%s frame buffer device\n", info->fix.id); 8118c2ecf20Sopenharmony_ci pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */ 8128c2ecf20Sopenharmony_ci return 0; 8138c2ecf20Sopenharmony_ci} 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci /* 8168c2ecf20Sopenharmony_ci * Cleanup 8178c2ecf20Sopenharmony_ci */ 8188c2ecf20Sopenharmony_ci/* static void xxxfb_remove(struct platform_device *pdev) */ 8198c2ecf20Sopenharmony_cistatic void xxxfb_remove(struct pci_dev *dev) 8208c2ecf20Sopenharmony_ci{ 8218c2ecf20Sopenharmony_ci struct fb_info *info = pci_get_drvdata(dev); 8228c2ecf20Sopenharmony_ci /* or platform_get_drvdata(pdev); */ 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci if (info) { 8258c2ecf20Sopenharmony_ci unregister_framebuffer(info); 8268c2ecf20Sopenharmony_ci fb_dealloc_cmap(&info->cmap); 8278c2ecf20Sopenharmony_ci /* ... */ 8288c2ecf20Sopenharmony_ci framebuffer_release(info); 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci} 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 8338c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 8348c2ecf20Sopenharmony_ci/** 8358c2ecf20Sopenharmony_ci * xxxfb_suspend - Optional but recommended function. Suspend the device. 8368c2ecf20Sopenharmony_ci * @dev: PCI device 8378c2ecf20Sopenharmony_ci * @msg: the suspend event code. 8388c2ecf20Sopenharmony_ci * 8398c2ecf20Sopenharmony_ci * See Documentation/driver-api/pm/devices.rst for more information 8408c2ecf20Sopenharmony_ci */ 8418c2ecf20Sopenharmony_cistatic int xxxfb_suspend(struct pci_dev *dev, pm_message_t msg) 8428c2ecf20Sopenharmony_ci{ 8438c2ecf20Sopenharmony_ci struct fb_info *info = pci_get_drvdata(dev); 8448c2ecf20Sopenharmony_ci struct xxxfb_par *par = info->par; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci /* suspend here */ 8478c2ecf20Sopenharmony_ci return 0; 8488c2ecf20Sopenharmony_ci} 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci/** 8518c2ecf20Sopenharmony_ci * xxxfb_resume - Optional but recommended function. Resume the device. 8528c2ecf20Sopenharmony_ci * @dev: PCI device 8538c2ecf20Sopenharmony_ci * 8548c2ecf20Sopenharmony_ci * See Documentation/driver-api/pm/devices.rst for more information 8558c2ecf20Sopenharmony_ci */ 8568c2ecf20Sopenharmony_cistatic int xxxfb_resume(struct pci_dev *dev) 8578c2ecf20Sopenharmony_ci{ 8588c2ecf20Sopenharmony_ci struct fb_info *info = pci_get_drvdata(dev); 8598c2ecf20Sopenharmony_ci struct xxxfb_par *par = info->par; 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci /* resume here */ 8628c2ecf20Sopenharmony_ci return 0; 8638c2ecf20Sopenharmony_ci} 8648c2ecf20Sopenharmony_ci#else 8658c2ecf20Sopenharmony_ci#define xxxfb_suspend NULL 8668c2ecf20Sopenharmony_ci#define xxxfb_resume NULL 8678c2ecf20Sopenharmony_ci#endif /* CONFIG_PM */ 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_cistatic const struct pci_device_id xxxfb_id_table[] = { 8708c2ecf20Sopenharmony_ci { PCI_VENDOR_ID_XXX, PCI_DEVICE_ID_XXX, 8718c2ecf20Sopenharmony_ci PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, 8728c2ecf20Sopenharmony_ci PCI_CLASS_MASK, 0 }, 8738c2ecf20Sopenharmony_ci { 0, } 8748c2ecf20Sopenharmony_ci}; 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci/* For PCI drivers */ 8778c2ecf20Sopenharmony_cistatic struct pci_driver xxxfb_driver = { 8788c2ecf20Sopenharmony_ci .name = "xxxfb", 8798c2ecf20Sopenharmony_ci .id_table = xxxfb_id_table, 8808c2ecf20Sopenharmony_ci .probe = xxxfb_probe, 8818c2ecf20Sopenharmony_ci .remove = xxxfb_remove, 8828c2ecf20Sopenharmony_ci .suspend = xxxfb_suspend, /* optional but recommended */ 8838c2ecf20Sopenharmony_ci .resume = xxxfb_resume, /* optional but recommended */ 8848c2ecf20Sopenharmony_ci}; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, xxxfb_id_table); 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ciint __init xxxfb_init(void) 8898c2ecf20Sopenharmony_ci{ 8908c2ecf20Sopenharmony_ci /* 8918c2ecf20Sopenharmony_ci * For kernel boot options (in 'video=xxxfb:<options>' format) 8928c2ecf20Sopenharmony_ci */ 8938c2ecf20Sopenharmony_ci#ifndef MODULE 8948c2ecf20Sopenharmony_ci char *option = NULL; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci if (fb_get_options("xxxfb", &option)) 8978c2ecf20Sopenharmony_ci return -ENODEV; 8988c2ecf20Sopenharmony_ci xxxfb_setup(option); 8998c2ecf20Sopenharmony_ci#endif 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci return pci_register_driver(&xxxfb_driver); 9028c2ecf20Sopenharmony_ci} 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_cistatic void __exit xxxfb_exit(void) 9058c2ecf20Sopenharmony_ci{ 9068c2ecf20Sopenharmony_ci pci_unregister_driver(&xxxfb_driver); 9078c2ecf20Sopenharmony_ci} 9088c2ecf20Sopenharmony_ci#else /* non PCI, platform drivers */ 9098c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 9108c2ecf20Sopenharmony_ci/* for platform devices */ 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 9138c2ecf20Sopenharmony_ci/** 9148c2ecf20Sopenharmony_ci * xxxfb_suspend - Optional but recommended function. Suspend the device. 9158c2ecf20Sopenharmony_ci * @dev: platform device 9168c2ecf20Sopenharmony_ci * @msg: the suspend event code. 9178c2ecf20Sopenharmony_ci * 9188c2ecf20Sopenharmony_ci * See Documentation/driver-api/pm/devices.rst for more information 9198c2ecf20Sopenharmony_ci */ 9208c2ecf20Sopenharmony_cistatic int xxxfb_suspend(struct platform_device *dev, pm_message_t msg) 9218c2ecf20Sopenharmony_ci{ 9228c2ecf20Sopenharmony_ci struct fb_info *info = platform_get_drvdata(dev); 9238c2ecf20Sopenharmony_ci struct xxxfb_par *par = info->par; 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci /* suspend here */ 9268c2ecf20Sopenharmony_ci return 0; 9278c2ecf20Sopenharmony_ci} 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci/** 9308c2ecf20Sopenharmony_ci * xxxfb_resume - Optional but recommended function. Resume the device. 9318c2ecf20Sopenharmony_ci * @dev: platform device 9328c2ecf20Sopenharmony_ci * 9338c2ecf20Sopenharmony_ci * See Documentation/driver-api/pm/devices.rst for more information 9348c2ecf20Sopenharmony_ci */ 9358c2ecf20Sopenharmony_cistatic int xxxfb_resume(struct platform_dev *dev) 9368c2ecf20Sopenharmony_ci{ 9378c2ecf20Sopenharmony_ci struct fb_info *info = platform_get_drvdata(dev); 9388c2ecf20Sopenharmony_ci struct xxxfb_par *par = info->par; 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci /* resume here */ 9418c2ecf20Sopenharmony_ci return 0; 9428c2ecf20Sopenharmony_ci} 9438c2ecf20Sopenharmony_ci#else 9448c2ecf20Sopenharmony_ci#define xxxfb_suspend NULL 9458c2ecf20Sopenharmony_ci#define xxxfb_resume NULL 9468c2ecf20Sopenharmony_ci#endif /* CONFIG_PM */ 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_cistatic struct platform_device_driver xxxfb_driver = { 9498c2ecf20Sopenharmony_ci .probe = xxxfb_probe, 9508c2ecf20Sopenharmony_ci .remove = xxxfb_remove, 9518c2ecf20Sopenharmony_ci .suspend = xxxfb_suspend, /* optional but recommended */ 9528c2ecf20Sopenharmony_ci .resume = xxxfb_resume, /* optional but recommended */ 9538c2ecf20Sopenharmony_ci .driver = { 9548c2ecf20Sopenharmony_ci .name = "xxxfb", 9558c2ecf20Sopenharmony_ci }, 9568c2ecf20Sopenharmony_ci}; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_cistatic struct platform_device *xxxfb_device; 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci#ifndef MODULE 9618c2ecf20Sopenharmony_ci /* 9628c2ecf20Sopenharmony_ci * Setup 9638c2ecf20Sopenharmony_ci */ 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci/* 9668c2ecf20Sopenharmony_ci * Only necessary if your driver takes special options, 9678c2ecf20Sopenharmony_ci * otherwise we fall back on the generic fb_setup(). 9688c2ecf20Sopenharmony_ci */ 9698c2ecf20Sopenharmony_ciint __init xxxfb_setup(char *options) 9708c2ecf20Sopenharmony_ci{ 9718c2ecf20Sopenharmony_ci /* Parse user specified options (`video=xxxfb:') */ 9728c2ecf20Sopenharmony_ci} 9738c2ecf20Sopenharmony_ci#endif /* MODULE */ 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_cistatic int __init xxxfb_init(void) 9768c2ecf20Sopenharmony_ci{ 9778c2ecf20Sopenharmony_ci int ret; 9788c2ecf20Sopenharmony_ci /* 9798c2ecf20Sopenharmony_ci * For kernel boot options (in 'video=xxxfb:<options>' format) 9808c2ecf20Sopenharmony_ci */ 9818c2ecf20Sopenharmony_ci#ifndef MODULE 9828c2ecf20Sopenharmony_ci char *option = NULL; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci if (fb_get_options("xxxfb", &option)) 9858c2ecf20Sopenharmony_ci return -ENODEV; 9868c2ecf20Sopenharmony_ci xxxfb_setup(option); 9878c2ecf20Sopenharmony_ci#endif 9888c2ecf20Sopenharmony_ci ret = platform_driver_register(&xxxfb_driver); 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci if (!ret) { 9918c2ecf20Sopenharmony_ci xxxfb_device = platform_device_register_simple("xxxfb", 0, 9928c2ecf20Sopenharmony_ci NULL, 0); 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci if (IS_ERR(xxxfb_device)) { 9958c2ecf20Sopenharmony_ci platform_driver_unregister(&xxxfb_driver); 9968c2ecf20Sopenharmony_ci ret = PTR_ERR(xxxfb_device); 9978c2ecf20Sopenharmony_ci } 9988c2ecf20Sopenharmony_ci } 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci return ret; 10018c2ecf20Sopenharmony_ci} 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_cistatic void __exit xxxfb_exit(void) 10048c2ecf20Sopenharmony_ci{ 10058c2ecf20Sopenharmony_ci platform_device_unregister(xxxfb_device); 10068c2ecf20Sopenharmony_ci platform_driver_unregister(&xxxfb_driver); 10078c2ecf20Sopenharmony_ci} 10088c2ecf20Sopenharmony_ci#endif /* CONFIG_PCI */ 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------- */ 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci /* 10148c2ecf20Sopenharmony_ci * Modularization 10158c2ecf20Sopenharmony_ci */ 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_cimodule_init(xxxfb_init); 10188c2ecf20Sopenharmony_cimodule_exit(xxxfb_exit); 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1021