1f7018c21STomi Valkeinen /*
2f7018c21STomi Valkeinen * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
3f7018c21STomi Valkeinen *
4f7018c21STomi Valkeinen * Modified to new api Jan 2001 by James Simmons ([email protected])
5f7018c21STomi Valkeinen *
6f7018c21STomi Valkeinen * Created 28 Dec 1997 by Geert Uytterhoeven
7f7018c21STomi Valkeinen *
8f7018c21STomi Valkeinen *
9f7018c21STomi Valkeinen * I have started rewriting this driver as a example of the upcoming new API
10f7018c21STomi Valkeinen * The primary goal is to remove the console code from fbdev and place it
11f7018c21STomi Valkeinen * into fbcon.c. This reduces the code and makes writing a new fbdev driver
12f7018c21STomi Valkeinen * easy since the author doesn't need to worry about console internals. It
13f7018c21STomi Valkeinen * also allows the ability to run fbdev without a console/tty system on top
14f7018c21STomi Valkeinen * of it.
15f7018c21STomi Valkeinen *
16f7018c21STomi Valkeinen * First the roles of struct fb_info and struct display have changed. Struct
17f7018c21STomi Valkeinen * display will go away. The way the new framebuffer console code will
18f7018c21STomi Valkeinen * work is that it will act to translate data about the tty/console in
19f7018c21STomi Valkeinen * struct vc_data to data in a device independent way in struct fb_info. Then
20f7018c21STomi Valkeinen * various functions in struct fb_ops will be called to store the device
21f7018c21STomi Valkeinen * dependent state in the par field in struct fb_info and to change the
22f7018c21STomi Valkeinen * hardware to that state. This allows a very clean separation of the fbdev
23f7018c21STomi Valkeinen * layer from the console layer. It also allows one to use fbdev on its own
24f7018c21STomi Valkeinen * which is a bounus for embedded devices. The reason this approach works is
25f7018c21STomi Valkeinen * for each framebuffer device when used as a tty/console device is allocated
26f7018c21STomi Valkeinen * a set of virtual terminals to it. Only one virtual terminal can be active
27f7018c21STomi Valkeinen * per framebuffer device. We already have all the data we need in struct
28f7018c21STomi Valkeinen * vc_data so why store a bunch of colormaps and other fbdev specific data
29f7018c21STomi Valkeinen * per virtual terminal.
30f7018c21STomi Valkeinen *
31f7018c21STomi Valkeinen * As you can see doing this makes the con parameter pretty much useless
32f7018c21STomi Valkeinen * for struct fb_ops functions, as it should be. Also having struct
33f7018c21STomi Valkeinen * fb_var_screeninfo and other data in fb_info pretty much eliminates the
34f7018c21STomi Valkeinen * need for get_fix and get_var. Once all drivers use the fix, var, and cmap
35f7018c21STomi Valkeinen * fbcon can be written around these fields. This will also eliminate the
36f7018c21STomi Valkeinen * need to regenerate struct fb_var_screeninfo, struct fb_fix_screeninfo
37f7018c21STomi Valkeinen * struct fb_cmap every time get_var, get_fix, get_cmap functions are called
38f7018c21STomi Valkeinen * as many drivers do now.
39f7018c21STomi Valkeinen *
40f7018c21STomi Valkeinen * This file is subject to the terms and conditions of the GNU General Public
41f7018c21STomi Valkeinen * License. See the file COPYING in the main directory of this archive for
42f7018c21STomi Valkeinen * more details.
43f7018c21STomi Valkeinen */
44f7018c21STomi Valkeinen
45145eed48SThomas Zimmermann #include <linux/aperture.h>
46f7018c21STomi Valkeinen #include <linux/module.h>
47f7018c21STomi Valkeinen #include <linux/kernel.h>
48f7018c21STomi Valkeinen #include <linux/errno.h>
49f7018c21STomi Valkeinen #include <linux/string.h>
50f7018c21STomi Valkeinen #include <linux/mm.h>
51f7018c21STomi Valkeinen #include <linux/slab.h>
52f7018c21STomi Valkeinen #include <linux/delay.h>
53f7018c21STomi Valkeinen #include <linux/fb.h>
54f7018c21STomi Valkeinen #include <linux/init.h>
55f7018c21STomi Valkeinen #include <linux/pci.h>
56f7018c21STomi Valkeinen
57f7018c21STomi Valkeinen /*
58f7018c21STomi Valkeinen * This is just simple sample code.
59f7018c21STomi Valkeinen *
60f7018c21STomi Valkeinen * No warranty that it actually compiles.
61f7018c21STomi Valkeinen * Even less warranty that it actually works :-)
62f7018c21STomi Valkeinen */
63f7018c21STomi Valkeinen
64f7018c21STomi Valkeinen /*
65f7018c21STomi Valkeinen * Driver data
66f7018c21STomi Valkeinen */
67f7018c21STomi Valkeinen static char *mode_option;
68f7018c21STomi Valkeinen
69f7018c21STomi Valkeinen /*
70f7018c21STomi Valkeinen * If your driver supports multiple boards, you should make the
71f7018c21STomi Valkeinen * below data types arrays, or allocate them dynamically (using kmalloc()).
72f7018c21STomi Valkeinen */
73f7018c21STomi Valkeinen
74f7018c21STomi Valkeinen /*
75f7018c21STomi Valkeinen * This structure defines the hardware state of the graphics card. Normally
76f7018c21STomi Valkeinen * you place this in a header file in linux/include/video. This file usually
77f7018c21STomi Valkeinen * also includes register information. That allows other driver subsystems
78f7018c21STomi Valkeinen * and userland applications the ability to use the same header file to
79f7018c21STomi Valkeinen * avoid duplicate work and easy porting of software.
80f7018c21STomi Valkeinen */
81f7018c21STomi Valkeinen struct xxx_par;
82f7018c21STomi Valkeinen
83f7018c21STomi Valkeinen /*
84f7018c21STomi Valkeinen * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
85f7018c21STomi Valkeinen * if we don't use modedb. If we do use modedb see xxxfb_init how to use it
86f7018c21STomi Valkeinen * to get a fb_var_screeninfo. Otherwise define a default var as well.
87f7018c21STomi Valkeinen */
88799b88deSBhumika Goyal static const struct fb_fix_screeninfo xxxfb_fix = {
89f7018c21STomi Valkeinen .id = "FB's name",
90f7018c21STomi Valkeinen .type = FB_TYPE_PACKED_PIXELS,
91f7018c21STomi Valkeinen .visual = FB_VISUAL_PSEUDOCOLOR,
92f7018c21STomi Valkeinen .xpanstep = 1,
93f7018c21STomi Valkeinen .ypanstep = 1,
94f7018c21STomi Valkeinen .ywrapstep = 1,
95f7018c21STomi Valkeinen .accel = FB_ACCEL_NONE,
96f7018c21STomi Valkeinen };
97f7018c21STomi Valkeinen
98f7018c21STomi Valkeinen /*
99f7018c21STomi Valkeinen * Modern graphical hardware not only supports pipelines but some
100fc378794SXiang wangx * also support multiple monitors where each display can have
101f7018c21STomi Valkeinen * its own unique data. In this case each display could be
102f7018c21STomi Valkeinen * represented by a separate framebuffer device thus a separate
103f7018c21STomi Valkeinen * struct fb_info. Now the struct xxx_par represents the graphics
104f7018c21STomi Valkeinen * hardware state thus only one exist per card. In this case the
105f7018c21STomi Valkeinen * struct xxx_par for each graphics card would be shared between
106f7018c21STomi Valkeinen * every struct fb_info that represents a framebuffer on that card.
107f7018c21STomi Valkeinen * This allows when one display changes it video resolution (info->var)
108f7018c21STomi Valkeinen * the other displays know instantly. Each display can always be
109f7018c21STomi Valkeinen * aware of the entire hardware state that affects it because they share
110f7018c21STomi Valkeinen * the same xxx_par struct. The other side of the coin is multiple
111f7018c21STomi Valkeinen * graphics cards that pass data around until it is finally displayed
112f7018c21STomi Valkeinen * on one monitor. Such examples are the voodoo 1 cards and high end
113f7018c21STomi Valkeinen * NUMA graphics servers. For this case we have a bunch of pars, each
114f7018c21STomi Valkeinen * one that represents a graphics state, that belong to one struct
115f7018c21STomi Valkeinen * fb_info. Their you would want to have *par point to a array of device
116f7018c21STomi Valkeinen * states and have each struct fb_ops function deal with all those
117f7018c21STomi Valkeinen * states. I hope this covers every possible hardware design. If not
118f7018c21STomi Valkeinen * feel free to send your ideas at [email protected]
119f7018c21STomi Valkeinen */
120f7018c21STomi Valkeinen
121f7018c21STomi Valkeinen /*
122f7018c21STomi Valkeinen * If your driver supports multiple boards or it supports multiple
123f7018c21STomi Valkeinen * framebuffers, you should make these arrays, or allocate them
124f7018c21STomi Valkeinen * dynamically using framebuffer_alloc() and free them with
125f7018c21STomi Valkeinen * framebuffer_release().
126f7018c21STomi Valkeinen */
127f7018c21STomi Valkeinen static struct fb_info info;
128f7018c21STomi Valkeinen
129f7018c21STomi Valkeinen /*
130f7018c21STomi Valkeinen * Each one represents the state of the hardware. Most hardware have
131f7018c21STomi Valkeinen * just one hardware state. These here represent the default state(s).
132f7018c21STomi Valkeinen */
133f7018c21STomi Valkeinen static struct xxx_par __initdata current_par;
134f7018c21STomi Valkeinen
135f7018c21STomi Valkeinen /**
136f7018c21STomi Valkeinen * xxxfb_open - Optional function. Called when the framebuffer is
137f7018c21STomi Valkeinen * first accessed.
138f7018c21STomi Valkeinen * @info: frame buffer structure that represents a single frame buffer
139f7018c21STomi Valkeinen * @user: tell us if the userland (value=1) or the console is accessing
140f7018c21STomi Valkeinen * the framebuffer.
141f7018c21STomi Valkeinen *
142f7018c21STomi Valkeinen * This function is the first function called in the framebuffer api.
143f7018c21STomi Valkeinen * Usually you don't need to provide this function. The case where it
144f7018c21STomi Valkeinen * is used is to change from a text mode hardware state to a graphics
145f7018c21STomi Valkeinen * mode state.
146f7018c21STomi Valkeinen *
147f7018c21STomi Valkeinen * Returns negative errno on error, or zero on success.
148f7018c21STomi Valkeinen */
xxxfb_open(struct fb_info * info,int user)149f7018c21STomi Valkeinen static int xxxfb_open(struct fb_info *info, int user)
150f7018c21STomi Valkeinen {
151f7018c21STomi Valkeinen return 0;
152f7018c21STomi Valkeinen }
153f7018c21STomi Valkeinen
154f7018c21STomi Valkeinen /**
155f7018c21STomi Valkeinen * xxxfb_release - Optional function. Called when the framebuffer
156f7018c21STomi Valkeinen * device is closed.
157f7018c21STomi Valkeinen * @info: frame buffer structure that represents a single frame buffer
158f7018c21STomi Valkeinen * @user: tell us if the userland (value=1) or the console is accessing
159f7018c21STomi Valkeinen * the framebuffer.
160f7018c21STomi Valkeinen *
161f7018c21STomi Valkeinen * Thus function is called when we close /dev/fb or the framebuffer
162f7018c21STomi Valkeinen * console system is released. Usually you don't need this function.
163f7018c21STomi Valkeinen * The case where it is usually used is to go from a graphics state
164f7018c21STomi Valkeinen * to a text mode state.
165f7018c21STomi Valkeinen *
166f7018c21STomi Valkeinen * Returns negative errno on error, or zero on success.
167f7018c21STomi Valkeinen */
xxxfb_release(struct fb_info * info,int user)168f7018c21STomi Valkeinen static int xxxfb_release(struct fb_info *info, int user)
169f7018c21STomi Valkeinen {
170f7018c21STomi Valkeinen return 0;
171f7018c21STomi Valkeinen }
172f7018c21STomi Valkeinen
173f7018c21STomi Valkeinen /**
174f7018c21STomi Valkeinen * xxxfb_check_var - Optional function. Validates a var passed in.
175f7018c21STomi Valkeinen * @var: frame buffer variable screen structure
176f7018c21STomi Valkeinen * @info: frame buffer structure that represents a single frame buffer
177f7018c21STomi Valkeinen *
178f7018c21STomi Valkeinen * Checks to see if the hardware supports the state requested by
179f7018c21STomi Valkeinen * var passed in. This function does not alter the hardware state!!!
180f7018c21STomi Valkeinen * This means the data stored in struct fb_info and struct xxx_par do
181f7018c21STomi Valkeinen * not change. This includes the var inside of struct fb_info.
182f7018c21STomi Valkeinen * Do NOT change these. This function can be called on its own if we
183f7018c21STomi Valkeinen * intent to only test a mode and not actually set it. The stuff in
184f7018c21STomi Valkeinen * modedb.c is a example of this. If the var passed in is slightly
185f7018c21STomi Valkeinen * off by what the hardware can support then we alter the var PASSED in
186f7018c21STomi Valkeinen * to what we can do.
187f7018c21STomi Valkeinen *
188f7018c21STomi Valkeinen * For values that are off, this function must round them _up_ to the
189f7018c21STomi Valkeinen * next value that is supported by the hardware. If the value is
190f7018c21STomi Valkeinen * greater than the highest value supported by the hardware, then this
191f7018c21STomi Valkeinen * function must return -EINVAL.
192f7018c21STomi Valkeinen *
193f7018c21STomi Valkeinen * Exception to the above rule: Some drivers have a fixed mode, ie,
194f7018c21STomi Valkeinen * the hardware is already set at boot up, and cannot be changed. In
195f7018c21STomi Valkeinen * this case, it is more acceptable that this function just return
196f7018c21STomi Valkeinen * a copy of the currently working var (info->var). Better is to not
197f7018c21STomi Valkeinen * implement this function, as the upper layer will do the copying
198f7018c21STomi Valkeinen * of the current var for you.
199f7018c21STomi Valkeinen *
200f7018c21STomi Valkeinen * Note: This is the only function where the contents of var can be
201f7018c21STomi Valkeinen * freely adjusted after the driver has been registered. If you find
202f7018c21STomi Valkeinen * that you have code outside of this function that alters the content
203f7018c21STomi Valkeinen * of var, then you are doing something wrong. Note also that the
204f7018c21STomi Valkeinen * contents of info->var must be left untouched at all times after
205f7018c21STomi Valkeinen * driver registration.
206f7018c21STomi Valkeinen *
207f7018c21STomi Valkeinen * Returns negative errno on error, or zero on success.
208f7018c21STomi Valkeinen */
xxxfb_check_var(struct fb_var_screeninfo * var,struct fb_info * info)209f7018c21STomi Valkeinen static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
210f7018c21STomi Valkeinen {
211f7018c21STomi Valkeinen /* ... */
212f7018c21STomi Valkeinen return 0;
213f7018c21STomi Valkeinen }
214f7018c21STomi Valkeinen
215f7018c21STomi Valkeinen /**
216f7018c21STomi Valkeinen * xxxfb_set_par - Optional function. Alters the hardware state.
217f7018c21STomi Valkeinen * @info: frame buffer structure that represents a single frame buffer
218f7018c21STomi Valkeinen *
219f7018c21STomi Valkeinen * Using the fb_var_screeninfo in fb_info we set the resolution of the
220f7018c21STomi Valkeinen * this particular framebuffer. This function alters the par AND the
221f7018c21STomi Valkeinen * fb_fix_screeninfo stored in fb_info. It doesn't not alter var in
222f7018c21STomi Valkeinen * fb_info since we are using that data. This means we depend on the
223f7018c21STomi Valkeinen * data in var inside fb_info to be supported by the hardware.
224f7018c21STomi Valkeinen *
225f7018c21STomi Valkeinen * This function is also used to recover/restore the hardware to a
226f7018c21STomi Valkeinen * known working state.
227f7018c21STomi Valkeinen *
228f7018c21STomi Valkeinen * xxxfb_check_var is always called before xxxfb_set_par to ensure that
229f7018c21STomi Valkeinen * the contents of var is always valid.
230f7018c21STomi Valkeinen *
231f7018c21STomi Valkeinen * Again if you can't change the resolution you don't need this function.
232f7018c21STomi Valkeinen *
233f7018c21STomi Valkeinen * However, even if your hardware does not support mode changing,
234f7018c21STomi Valkeinen * a set_par might be needed to at least initialize the hardware to
235f7018c21STomi Valkeinen * a known working state, especially if it came back from another
236f7018c21STomi Valkeinen * process that also modifies the same hardware, such as X.
237f7018c21STomi Valkeinen *
238f7018c21STomi Valkeinen * If this is the case, a combination such as the following should work:
239f7018c21STomi Valkeinen *
240f7018c21STomi Valkeinen * static int xxxfb_check_var(struct fb_var_screeninfo *var,
241f7018c21STomi Valkeinen * struct fb_info *info)
242f7018c21STomi Valkeinen * {
243f7018c21STomi Valkeinen * *var = info->var;
244f7018c21STomi Valkeinen * return 0;
245f7018c21STomi Valkeinen * }
246f7018c21STomi Valkeinen *
247f7018c21STomi Valkeinen * static int xxxfb_set_par(struct fb_info *info)
248f7018c21STomi Valkeinen * {
249f7018c21STomi Valkeinen * init your hardware here
250f7018c21STomi Valkeinen * }
251f7018c21STomi Valkeinen *
252f7018c21STomi Valkeinen * Returns negative errno on error, or zero on success.
253f7018c21STomi Valkeinen */
xxxfb_set_par(struct fb_info * info)254f7018c21STomi Valkeinen static int xxxfb_set_par(struct fb_info *info)
255f7018c21STomi Valkeinen {
256f7018c21STomi Valkeinen struct xxx_par *par = info->par;
257f7018c21STomi Valkeinen /* ... */
258f7018c21STomi Valkeinen return 0;
259f7018c21STomi Valkeinen }
260f7018c21STomi Valkeinen
261f7018c21STomi Valkeinen /**
262f7018c21STomi Valkeinen * xxxfb_setcolreg - Optional function. Sets a color register.
263f7018c21STomi Valkeinen * @regno: Which register in the CLUT we are programming
264f7018c21STomi Valkeinen * @red: The red value which can be up to 16 bits wide
265f7018c21STomi Valkeinen * @green: The green value which can be up to 16 bits wide
266f7018c21STomi Valkeinen * @blue: The blue value which can be up to 16 bits wide.
267f7018c21STomi Valkeinen * @transp: If supported, the alpha value which can be up to 16 bits wide.
268f7018c21STomi Valkeinen * @info: frame buffer info structure
269f7018c21STomi Valkeinen *
270f7018c21STomi Valkeinen * Set a single color register. The values supplied have a 16 bit
271f7018c21STomi Valkeinen * magnitude which needs to be scaled in this function for the hardware.
272f7018c21STomi Valkeinen * Things to take into consideration are how many color registers, if
273f7018c21STomi Valkeinen * any, are supported with the current color visual. With truecolor mode
274f7018c21STomi Valkeinen * no color palettes are supported. Here a pseudo palette is created
275f7018c21STomi Valkeinen * which we store the value in pseudo_palette in struct fb_info. For
276f7018c21STomi Valkeinen * pseudocolor mode we have a limited color palette. To deal with this
277f7018c21STomi Valkeinen * we can program what color is displayed for a particular pixel value.
278f7018c21STomi Valkeinen * DirectColor is similar in that we can program each color field. If
279f7018c21STomi Valkeinen * we have a static colormap we don't need to implement this function.
280f7018c21STomi Valkeinen *
281f7018c21STomi Valkeinen * Returns negative errno on error, or zero on success.
282f7018c21STomi Valkeinen */
xxxfb_setcolreg(unsigned regno,unsigned red,unsigned green,unsigned blue,unsigned transp,struct fb_info * info)283f7018c21STomi Valkeinen static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
284f7018c21STomi Valkeinen unsigned blue, unsigned transp,
285f7018c21STomi Valkeinen struct fb_info *info)
286f7018c21STomi Valkeinen {
287f7018c21STomi Valkeinen if (regno >= 256) /* no. of hw registers */
288f7018c21STomi Valkeinen return -EINVAL;
289f7018c21STomi Valkeinen /*
290f7018c21STomi Valkeinen * Program hardware... do anything you want with transp
291f7018c21STomi Valkeinen */
292f7018c21STomi Valkeinen
293f7018c21STomi Valkeinen /* grayscale works only partially under directcolor */
294f7018c21STomi Valkeinen if (info->var.grayscale) {
295f7018c21STomi Valkeinen /* grayscale = 0.30*R + 0.59*G + 0.11*B */
296f7018c21STomi Valkeinen red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
297f7018c21STomi Valkeinen }
298f7018c21STomi Valkeinen
299f7018c21STomi Valkeinen /* Directcolor:
300f7018c21STomi Valkeinen * var->{color}.offset contains start of bitfield
301f7018c21STomi Valkeinen * var->{color}.length contains length of bitfield
302f7018c21STomi Valkeinen * {hardwarespecific} contains width of DAC
303f7018c21STomi Valkeinen * pseudo_palette[X] is programmed to (X << red.offset) |
304f7018c21STomi Valkeinen * (X << green.offset) |
305f7018c21STomi Valkeinen * (X << blue.offset)
306f7018c21STomi Valkeinen * RAMDAC[X] is programmed to (red, green, blue)
307f7018c21STomi Valkeinen * color depth = SUM(var->{color}.length)
308f7018c21STomi Valkeinen *
309f7018c21STomi Valkeinen * Pseudocolor:
310f7018c21STomi Valkeinen * var->{color}.offset is 0 unless the palette index takes less than
311f7018c21STomi Valkeinen * bits_per_pixel bits and is stored in the upper
312f7018c21STomi Valkeinen * bits of the pixel value
313f7018c21STomi Valkeinen * var->{color}.length is set so that 1 << length is the number of
314f7018c21STomi Valkeinen * available palette entries
315f7018c21STomi Valkeinen * pseudo_palette is not used
316f7018c21STomi Valkeinen * RAMDAC[X] is programmed to (red, green, blue)
317f7018c21STomi Valkeinen * color depth = var->{color}.length
318f7018c21STomi Valkeinen *
319f7018c21STomi Valkeinen * Static pseudocolor:
320f7018c21STomi Valkeinen * same as Pseudocolor, but the RAMDAC is not programmed (read-only)
321f7018c21STomi Valkeinen *
322f7018c21STomi Valkeinen * Mono01/Mono10:
323f7018c21STomi Valkeinen * Has only 2 values, black on white or white on black (fg on bg),
324f7018c21STomi Valkeinen * var->{color}.offset is 0
325f7018c21STomi Valkeinen * white = (1 << var->{color}.length) - 1, black = 0
326f7018c21STomi Valkeinen * pseudo_palette is not used
327f7018c21STomi Valkeinen * RAMDAC does not exist
328f7018c21STomi Valkeinen * color depth is always 2
329f7018c21STomi Valkeinen *
330f7018c21STomi Valkeinen * Truecolor:
331f7018c21STomi Valkeinen * does not use RAMDAC (usually has 3 of them).
332f7018c21STomi Valkeinen * var->{color}.offset contains start of bitfield
333f7018c21STomi Valkeinen * var->{color}.length contains length of bitfield
334f7018c21STomi Valkeinen * pseudo_palette is programmed to (red << red.offset) |
335f7018c21STomi Valkeinen * (green << green.offset) |
336f7018c21STomi Valkeinen * (blue << blue.offset) |
337f7018c21STomi Valkeinen * (transp << transp.offset)
338f7018c21STomi Valkeinen * RAMDAC does not exist
339f7018c21STomi Valkeinen * color depth = SUM(var->{color}.length})
340f7018c21STomi Valkeinen *
341f7018c21STomi Valkeinen * The color depth is used by fbcon for choosing the logo and also
342f7018c21STomi Valkeinen * for color palette transformation if color depth < 4
343f7018c21STomi Valkeinen *
344f7018c21STomi Valkeinen * As can be seen from the above, the field bits_per_pixel is _NOT_
345f7018c21STomi Valkeinen * a criteria for describing the color visual.
346f7018c21STomi Valkeinen *
347f7018c21STomi Valkeinen * A common mistake is assuming that bits_per_pixel <= 8 is pseudocolor,
348f7018c21STomi Valkeinen * and higher than that, true/directcolor. This is incorrect, one needs
349f7018c21STomi Valkeinen * to look at the fix->visual.
350f7018c21STomi Valkeinen *
351f7018c21STomi Valkeinen * Another common mistake is using bits_per_pixel to calculate the color
352f7018c21STomi Valkeinen * depth. The bits_per_pixel field does not directly translate to color
353f7018c21STomi Valkeinen * depth. You have to compute for the color depth (using the color
354f7018c21STomi Valkeinen * bitfields) and fix->visual as seen above.
355f7018c21STomi Valkeinen */
356f7018c21STomi Valkeinen
357f7018c21STomi Valkeinen /*
358f7018c21STomi Valkeinen * This is the point where the color is converted to something that
359f7018c21STomi Valkeinen * is acceptable by the hardware.
360f7018c21STomi Valkeinen */
361f7018c21STomi Valkeinen #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
362f7018c21STomi Valkeinen red = CNVT_TOHW(red, info->var.red.length);
363f7018c21STomi Valkeinen green = CNVT_TOHW(green, info->var.green.length);
364f7018c21STomi Valkeinen blue = CNVT_TOHW(blue, info->var.blue.length);
365f7018c21STomi Valkeinen transp = CNVT_TOHW(transp, info->var.transp.length);
366f7018c21STomi Valkeinen #undef CNVT_TOHW
367f7018c21STomi Valkeinen /*
368f7018c21STomi Valkeinen * This is the point where the function feeds the color to the hardware
369f7018c21STomi Valkeinen * palette after converting the colors to something acceptable by
370f7018c21STomi Valkeinen * the hardware. Note, only FB_VISUAL_DIRECTCOLOR and
371f7018c21STomi Valkeinen * FB_VISUAL_PSEUDOCOLOR visuals need to write to the hardware palette.
372f7018c21STomi Valkeinen * If you have code that writes to the hardware CLUT, and it's not
373f7018c21STomi Valkeinen * any of the above visuals, then you are doing something wrong.
374f7018c21STomi Valkeinen */
375f7018c21STomi Valkeinen if (info->fix.visual == FB_VISUAL_DIRECTCOLOR ||
376f7018c21STomi Valkeinen info->fix.visual == FB_VISUAL_TRUECOLOR)
377f7018c21STomi Valkeinen write_{red|green|blue|transp}_to_clut();
378f7018c21STomi Valkeinen
379f7018c21STomi Valkeinen /* This is the point were you need to fill up the contents of
380f7018c21STomi Valkeinen * info->pseudo_palette. This structure is used _only_ by fbcon, thus
381f7018c21STomi Valkeinen * it only contains 16 entries to match the number of colors supported
382f7018c21STomi Valkeinen * by the console. The pseudo_palette is used only if the visual is
383f7018c21STomi Valkeinen * in directcolor or truecolor mode. With other visuals, the
384f7018c21STomi Valkeinen * pseudo_palette is not used. (This might change in the future.)
385f7018c21STomi Valkeinen *
386f7018c21STomi Valkeinen * The contents of the pseudo_palette is in raw pixel format. Ie, each
387f7018c21STomi Valkeinen * entry can be written directly to the framebuffer without any conversion.
388f7018c21STomi Valkeinen * The pseudo_palette is (void *). However, if using the generic
389f7018c21STomi Valkeinen * drawing functions (cfb_imageblit, cfb_fillrect), the pseudo_palette
390f7018c21STomi Valkeinen * must be casted to (u32 *) _regardless_ of the bits per pixel. If the
391f7018c21STomi Valkeinen * driver is using its own drawing functions, then it can use whatever
392f7018c21STomi Valkeinen * size it wants.
393f7018c21STomi Valkeinen */
394f7018c21STomi Valkeinen if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
395f7018c21STomi Valkeinen info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
396f7018c21STomi Valkeinen u32 v;
397f7018c21STomi Valkeinen
398f7018c21STomi Valkeinen if (regno >= 16)
399f7018c21STomi Valkeinen return -EINVAL;
400f7018c21STomi Valkeinen
401f7018c21STomi Valkeinen v = (red << info->var.red.offset) |
402f7018c21STomi Valkeinen (green << info->var.green.offset) |
403f7018c21STomi Valkeinen (blue << info->var.blue.offset) |
404f7018c21STomi Valkeinen (transp << info->var.transp.offset);
405f7018c21STomi Valkeinen
406f7018c21STomi Valkeinen ((u32*)(info->pseudo_palette))[regno] = v;
407f7018c21STomi Valkeinen }
408f7018c21STomi Valkeinen
409f7018c21STomi Valkeinen /* ... */
410f7018c21STomi Valkeinen return 0;
411f7018c21STomi Valkeinen }
412f7018c21STomi Valkeinen
413f7018c21STomi Valkeinen /**
414f7018c21STomi Valkeinen * xxxfb_pan_display - NOT a required function. Pans the display.
415f7018c21STomi Valkeinen * @var: frame buffer variable screen structure
416f7018c21STomi Valkeinen * @info: frame buffer structure that represents a single frame buffer
417f7018c21STomi Valkeinen *
418f7018c21STomi Valkeinen * Pan (or wrap, depending on the `vmode' field) the display using the
419f7018c21STomi Valkeinen * `xoffset' and `yoffset' fields of the `var' structure.
420f7018c21STomi Valkeinen * If the values don't fit, return -EINVAL.
421f7018c21STomi Valkeinen *
422f7018c21STomi Valkeinen * Returns negative errno on error, or zero on success.
423f7018c21STomi Valkeinen */
xxxfb_pan_display(struct fb_var_screeninfo * var,struct fb_info * info)424f7018c21STomi Valkeinen static int xxxfb_pan_display(struct fb_var_screeninfo *var,
425f7018c21STomi Valkeinen struct fb_info *info)
426f7018c21STomi Valkeinen {
427f7018c21STomi Valkeinen /*
428f7018c21STomi Valkeinen * If your hardware does not support panning, _do_ _not_ implement this
429f7018c21STomi Valkeinen * function. Creating a dummy function will just confuse user apps.
430f7018c21STomi Valkeinen */
431f7018c21STomi Valkeinen
432f7018c21STomi Valkeinen /*
433f7018c21STomi Valkeinen * Note that even if this function is fully functional, a setting of
434f7018c21STomi Valkeinen * 0 in both xpanstep and ypanstep means that this function will never
435f7018c21STomi Valkeinen * get called.
436f7018c21STomi Valkeinen */
437f7018c21STomi Valkeinen
438f7018c21STomi Valkeinen /* ... */
439f7018c21STomi Valkeinen return 0;
440f7018c21STomi Valkeinen }
441f7018c21STomi Valkeinen
442f7018c21STomi Valkeinen /**
443f7018c21STomi Valkeinen * xxxfb_blank - NOT a required function. Blanks the display.
444f7018c21STomi Valkeinen * @blank_mode: the blank mode we want.
445f7018c21STomi Valkeinen * @info: frame buffer structure that represents a single frame buffer
446f7018c21STomi Valkeinen *
447f7018c21STomi Valkeinen * Blank the screen if blank_mode != FB_BLANK_UNBLANK, else unblank.
448f7018c21STomi Valkeinen * Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
449f7018c21STomi Valkeinen * e.g. a video mode which doesn't support it.
450f7018c21STomi Valkeinen *
451f7018c21STomi Valkeinen * Implements VESA suspend and powerdown modes on hardware that supports
452f7018c21STomi Valkeinen * disabling hsync/vsync:
453f7018c21STomi Valkeinen *
454f7018c21STomi Valkeinen * FB_BLANK_NORMAL = display is blanked, syncs are on.
455f7018c21STomi Valkeinen * FB_BLANK_HSYNC_SUSPEND = hsync off
456f7018c21STomi Valkeinen * FB_BLANK_VSYNC_SUSPEND = vsync off
457f7018c21STomi Valkeinen * FB_BLANK_POWERDOWN = hsync and vsync off
458f7018c21STomi Valkeinen *
459f7018c21STomi Valkeinen * If implementing this function, at least support FB_BLANK_UNBLANK.
460f7018c21STomi Valkeinen * Return !0 for any modes that are unimplemented.
461f7018c21STomi Valkeinen *
462f7018c21STomi Valkeinen */
xxxfb_blank(int blank_mode,struct fb_info * info)463f7018c21STomi Valkeinen static int xxxfb_blank(int blank_mode, struct fb_info *info)
464f7018c21STomi Valkeinen {
465f7018c21STomi Valkeinen /* ... */
466f7018c21STomi Valkeinen return 0;
467f7018c21STomi Valkeinen }
468f7018c21STomi Valkeinen
469f7018c21STomi Valkeinen /* ------------ Accelerated Functions --------------------- */
470f7018c21STomi Valkeinen
471f7018c21STomi Valkeinen /*
472f7018c21STomi Valkeinen * We provide our own functions if we have hardware acceleration
473f7018c21STomi Valkeinen * or non packed pixel format layouts. If we have no hardware
474f7018c21STomi Valkeinen * acceleration, we can use a generic unaccelerated function. If using
475f7018c21STomi Valkeinen * a pack pixel format just use the functions in cfb_*.c. Each file
476f7018c21STomi Valkeinen * has one of the three different accel functions we support.
477f7018c21STomi Valkeinen */
478f7018c21STomi Valkeinen
479f7018c21STomi Valkeinen /**
480f7018c21STomi Valkeinen * xxxfb_fillrect - REQUIRED function. Can use generic routines if
481f7018c21STomi Valkeinen * non acclerated hardware and packed pixel based.
482f7018c21STomi Valkeinen * Draws a rectangle on the screen.
483f7018c21STomi Valkeinen *
484f7018c21STomi Valkeinen * @info: frame buffer structure that represents a single frame buffer
485f7018c21STomi Valkeinen * @region: The structure representing the rectangular region we
486f7018c21STomi Valkeinen * wish to draw to.
487f7018c21STomi Valkeinen *
488f7018c21STomi Valkeinen * This drawing operation places/removes a retangle on the screen
489f7018c21STomi Valkeinen * depending on the rastering operation with the value of color which
490f7018c21STomi Valkeinen * is in the current color depth format.
491f7018c21STomi Valkeinen */
xxxfb_fillrect(struct fb_info * p,const struct fb_fillrect * region)492f7018c21STomi Valkeinen void xxxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region)
493f7018c21STomi Valkeinen {
494f7018c21STomi Valkeinen /* Meaning of struct fb_fillrect
495f7018c21STomi Valkeinen *
496f7018c21STomi Valkeinen * @dx: The x and y corrdinates of the upper left hand corner of the
497f7018c21STomi Valkeinen * @dy: area we want to draw to.
498f7018c21STomi Valkeinen * @width: How wide the rectangle is we want to draw.
499f7018c21STomi Valkeinen * @height: How tall the rectangle is we want to draw.
500f7018c21STomi Valkeinen * @color: The color to fill in the rectangle with.
501f7018c21STomi Valkeinen * @rop: The raster operation. We can draw the rectangle with a COPY
502f7018c21STomi Valkeinen * of XOR which provides erasing effect.
503f7018c21STomi Valkeinen */
504f7018c21STomi Valkeinen }
505f7018c21STomi Valkeinen
506f7018c21STomi Valkeinen /**
5071148836fSHelge Deller * xxxfb_copyarea - REQUIRED function. Can use generic routines if
5081148836fSHelge Deller * non acclerated hardware and packed pixel based.
509f7018c21STomi Valkeinen * Copies one area of the screen to another area.
510f7018c21STomi Valkeinen *
511f7018c21STomi Valkeinen * @info: frame buffer structure that represents a single frame buffer
512f7018c21STomi Valkeinen * @area: Structure providing the data to copy the framebuffer contents
513f7018c21STomi Valkeinen * from one region to another.
514f7018c21STomi Valkeinen *
5151148836fSHelge Deller * This drawing operation copies a rectangular area from one area of the
516f7018c21STomi Valkeinen * screen to another area.
517f7018c21STomi Valkeinen */
xxxfb_copyarea(struct fb_info * p,const struct fb_copyarea * area)518f7018c21STomi Valkeinen void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
519f7018c21STomi Valkeinen {
520f7018c21STomi Valkeinen /*
521f7018c21STomi Valkeinen * @dx: The x and y coordinates of the upper left hand corner of the
522f7018c21STomi Valkeinen * @dy: destination area on the screen.
523f7018c21STomi Valkeinen * @width: How wide the rectangle is we want to copy.
524f7018c21STomi Valkeinen * @height: How tall the rectangle is we want to copy.
525f7018c21STomi Valkeinen * @sx: The x and y coordinates of the upper left hand corner of the
526f7018c21STomi Valkeinen * @sy: source area on the screen.
527f7018c21STomi Valkeinen */
528f7018c21STomi Valkeinen }
529f7018c21STomi Valkeinen
530f7018c21STomi Valkeinen
531f7018c21STomi Valkeinen /**
532f7018c21STomi Valkeinen * xxxfb_imageblit - REQUIRED function. Can use generic routines if
533f7018c21STomi Valkeinen * non acclerated hardware and packed pixel based.
534f7018c21STomi Valkeinen * Copies a image from system memory to the screen.
535f7018c21STomi Valkeinen *
536f7018c21STomi Valkeinen * @info: frame buffer structure that represents a single frame buffer
537f7018c21STomi Valkeinen * @image: structure defining the image.
538f7018c21STomi Valkeinen *
539f7018c21STomi Valkeinen * This drawing operation draws a image on the screen. It can be a
540f7018c21STomi Valkeinen * mono image (needed for font handling) or a color image (needed for
541f7018c21STomi Valkeinen * tux).
542f7018c21STomi Valkeinen */
xxxfb_imageblit(struct fb_info * p,const struct fb_image * image)543f7018c21STomi Valkeinen void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image)
544f7018c21STomi Valkeinen {
545f7018c21STomi Valkeinen /*
546f7018c21STomi Valkeinen * @dx: The x and y coordinates of the upper left hand corner of the
547f7018c21STomi Valkeinen * @dy: destination area to place the image on the screen.
548f7018c21STomi Valkeinen * @width: How wide the image is we want to copy.
549f7018c21STomi Valkeinen * @height: How tall the image is we want to copy.
550f7018c21STomi Valkeinen * @fg_color: For mono bitmap images this is color data for
551f7018c21STomi Valkeinen * @bg_color: the foreground and background of the image to
552f7018c21STomi Valkeinen * write directly to the frmaebuffer.
553f7018c21STomi Valkeinen * @depth: How many bits represent a single pixel for this image.
554f7018c21STomi Valkeinen * @data: The actual data used to construct the image on the display.
555f7018c21STomi Valkeinen * @cmap: The colormap used for color images.
556f7018c21STomi Valkeinen */
557f7018c21STomi Valkeinen
558f7018c21STomi Valkeinen /*
559f7018c21STomi Valkeinen * The generic function, cfb_imageblit, expects that the bitmap scanlines are
560f7018c21STomi Valkeinen * padded to the next byte. Most hardware accelerators may require padding to
561f7018c21STomi Valkeinen * the next u16 or the next u32. If that is the case, the driver can specify
562f7018c21STomi Valkeinen * this by setting info->pixmap.scan_align = 2 or 4. See a more
563f7018c21STomi Valkeinen * comprehensive description of the pixmap below.
564f7018c21STomi Valkeinen */
565f7018c21STomi Valkeinen }
566f7018c21STomi Valkeinen
567f7018c21STomi Valkeinen /**
568f7018c21STomi Valkeinen * xxxfb_cursor - OPTIONAL. If your hardware lacks support
569f7018c21STomi Valkeinen * for a cursor, leave this field NULL.
570f7018c21STomi Valkeinen *
571f7018c21STomi Valkeinen * @info: frame buffer structure that represents a single frame buffer
572f7018c21STomi Valkeinen * @cursor: structure defining the cursor to draw.
573f7018c21STomi Valkeinen *
574f7018c21STomi Valkeinen * This operation is used to set or alter the properities of the
575f7018c21STomi Valkeinen * cursor.
576f7018c21STomi Valkeinen *
577f7018c21STomi Valkeinen * Returns negative errno on error, or zero on success.
578f7018c21STomi Valkeinen */
xxxfb_cursor(struct fb_info * info,struct fb_cursor * cursor)579f7018c21STomi Valkeinen int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
580f7018c21STomi Valkeinen {
581f7018c21STomi Valkeinen /*
582f7018c21STomi Valkeinen * @set: Which fields we are altering in struct fb_cursor
583f7018c21STomi Valkeinen * @enable: Disable or enable the cursor
584f7018c21STomi Valkeinen * @rop: The bit operation we want to do.
585f7018c21STomi Valkeinen * @mask: This is the cursor mask bitmap.
586f7018c21STomi Valkeinen * @dest: A image of the area we are going to display the cursor.
587f7018c21STomi Valkeinen * Used internally by the driver.
588f7018c21STomi Valkeinen * @hot: The hot spot.
589f7018c21STomi Valkeinen * @image: The actual data for the cursor image.
590f7018c21STomi Valkeinen *
591f7018c21STomi Valkeinen * NOTES ON FLAGS (cursor->set):
592f7018c21STomi Valkeinen *
593f7018c21STomi Valkeinen * FB_CUR_SETIMAGE - the cursor image has changed (cursor->image.data)
594f7018c21STomi Valkeinen * FB_CUR_SETPOS - the cursor position has changed (cursor->image.dx|dy)
595f7018c21STomi Valkeinen * FB_CUR_SETHOT - the cursor hot spot has changed (cursor->hot.dx|dy)
596f7018c21STomi Valkeinen * FB_CUR_SETCMAP - the cursor colors has changed (cursor->fg_color|bg_color)
597f7018c21STomi Valkeinen * FB_CUR_SETSHAPE - the cursor bitmask has changed (cursor->mask)
598f7018c21STomi Valkeinen * FB_CUR_SETSIZE - the cursor size has changed (cursor->width|height)
599f7018c21STomi Valkeinen * FB_CUR_SETALL - everything has changed
600f7018c21STomi Valkeinen *
601f7018c21STomi Valkeinen * NOTES ON ROPs (cursor->rop, Raster Operation)
602f7018c21STomi Valkeinen *
603f7018c21STomi Valkeinen * ROP_XOR - cursor->image.data XOR cursor->mask
604f7018c21STomi Valkeinen * ROP_COPY - curosr->image.data AND cursor->mask
605f7018c21STomi Valkeinen *
606f7018c21STomi Valkeinen * OTHER NOTES:
607f7018c21STomi Valkeinen *
608f7018c21STomi Valkeinen * - fbcon only supports a 2-color cursor (cursor->image.depth = 1)
609f7018c21STomi Valkeinen * - The fb_cursor structure, @cursor, _will_ always contain valid
610f7018c21STomi Valkeinen * fields, whether any particular bitfields in cursor->set is set
611f7018c21STomi Valkeinen * or not.
612f7018c21STomi Valkeinen */
613f7018c21STomi Valkeinen }
614f7018c21STomi Valkeinen
615f7018c21STomi Valkeinen /**
616f7018c21STomi Valkeinen * xxxfb_sync - NOT a required function. Normally the accel engine
617f7018c21STomi Valkeinen * for a graphics card take a specific amount of time.
618f7018c21STomi Valkeinen * Often we have to wait for the accelerator to finish
619f7018c21STomi Valkeinen * its operation before we can write to the framebuffer
620f7018c21STomi Valkeinen * so we can have consistent display output.
621f7018c21STomi Valkeinen *
622f7018c21STomi Valkeinen * @info: frame buffer structure that represents a single frame buffer
623f7018c21STomi Valkeinen *
624f7018c21STomi Valkeinen * If the driver has implemented its own hardware-based drawing function,
625f7018c21STomi Valkeinen * implementing this function is highly recommended.
626f7018c21STomi Valkeinen */
xxxfb_sync(struct fb_info * info)627f7018c21STomi Valkeinen int xxxfb_sync(struct fb_info *info)
628f7018c21STomi Valkeinen {
629f7018c21STomi Valkeinen return 0;
630f7018c21STomi Valkeinen }
631f7018c21STomi Valkeinen
632f7018c21STomi Valkeinen /*
633f7018c21STomi Valkeinen * Frame buffer operations
634f7018c21STomi Valkeinen */
635f7018c21STomi Valkeinen
6368a48ac33SJani Nikula static const struct fb_ops xxxfb_ops = {
637f7018c21STomi Valkeinen .owner = THIS_MODULE,
638f7018c21STomi Valkeinen .fb_open = xxxfb_open,
639f7018c21STomi Valkeinen .fb_read = xxxfb_read,
640f7018c21STomi Valkeinen .fb_write = xxxfb_write,
641f7018c21STomi Valkeinen .fb_release = xxxfb_release,
642f7018c21STomi Valkeinen .fb_check_var = xxxfb_check_var,
643f7018c21STomi Valkeinen .fb_set_par = xxxfb_set_par,
644f7018c21STomi Valkeinen .fb_setcolreg = xxxfb_setcolreg,
645f7018c21STomi Valkeinen .fb_blank = xxxfb_blank,
646f7018c21STomi Valkeinen .fb_pan_display = xxxfb_pan_display,
647f7018c21STomi Valkeinen .fb_fillrect = xxxfb_fillrect, /* Needed !!! */
6481148836fSHelge Deller .fb_copyarea = xxxfb_copyarea, /* Needed !!! */
649f7018c21STomi Valkeinen .fb_imageblit = xxxfb_imageblit, /* Needed !!! */
650f7018c21STomi Valkeinen .fb_cursor = xxxfb_cursor, /* Optional !!! */
651f7018c21STomi Valkeinen .fb_sync = xxxfb_sync,
652f7018c21STomi Valkeinen .fb_ioctl = xxxfb_ioctl,
653f7018c21STomi Valkeinen .fb_mmap = xxxfb_mmap,
654f7018c21STomi Valkeinen };
655f7018c21STomi Valkeinen
656f7018c21STomi Valkeinen /* ------------------------------------------------------------------------- */
657f7018c21STomi Valkeinen
658f7018c21STomi Valkeinen /*
659f7018c21STomi Valkeinen * Initialization
660f7018c21STomi Valkeinen */
661f7018c21STomi Valkeinen
662f7018c21STomi Valkeinen /* static int __init xxfb_probe (struct platform_device *pdev) -- for platform devs */
xxxfb_probe(struct pci_dev * dev,const struct pci_device_id * ent)663f7018c21STomi Valkeinen static int xxxfb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
664f7018c21STomi Valkeinen {
665f7018c21STomi Valkeinen struct fb_info *info;
666f7018c21STomi Valkeinen struct xxx_par *par;
667f7018c21STomi Valkeinen struct device *device = &dev->dev; /* or &pdev->dev */
668f7018c21STomi Valkeinen int cmap_len, retval;
669f7018c21STomi Valkeinen
670f7018c21STomi Valkeinen /*
671145eed48SThomas Zimmermann * Remove firmware-based drivers that create resource conflicts.
672145eed48SThomas Zimmermann */
673145eed48SThomas Zimmermann retval = aperture_remove_conflicting_pci_devices(pdev, "xxxfb");
674145eed48SThomas Zimmermann if (retval)
675145eed48SThomas Zimmermann return retval;
676145eed48SThomas Zimmermann
677145eed48SThomas Zimmermann /*
678f7018c21STomi Valkeinen * Dynamically allocate info and par
679f7018c21STomi Valkeinen */
680f7018c21STomi Valkeinen info = framebuffer_alloc(sizeof(struct xxx_par), device);
681f7018c21STomi Valkeinen
682f7018c21STomi Valkeinen if (!info) {
683f7018c21STomi Valkeinen /* goto error path */
684f7018c21STomi Valkeinen }
685f7018c21STomi Valkeinen
686f7018c21STomi Valkeinen par = info->par;
687f7018c21STomi Valkeinen
688f7018c21STomi Valkeinen /*
689f7018c21STomi Valkeinen * Here we set the screen_base to the virtual memory address
690f7018c21STomi Valkeinen * for the framebuffer. Usually we obtain the resource address
691f7018c21STomi Valkeinen * from the bus layer and then translate it to virtual memory
692f7018c21STomi Valkeinen * space via ioremap. Consult ioport.h.
693f7018c21STomi Valkeinen */
694f7018c21STomi Valkeinen info->screen_base = framebuffer_virtual_memory;
695f7018c21STomi Valkeinen info->fbops = &xxxfb_ops;
696f7018c21STomi Valkeinen info->fix = xxxfb_fix;
697f7018c21STomi Valkeinen info->pseudo_palette = pseudo_palette; /* The pseudopalette is an
698f7018c21STomi Valkeinen * 16-member array
699f7018c21STomi Valkeinen */
700f7018c21STomi Valkeinen /*
701f7018c21STomi Valkeinen * Set up flags to indicate what sort of acceleration your
702f7018c21STomi Valkeinen * driver can provide (pan/wrap/copyarea/etc.) and whether it
703f7018c21STomi Valkeinen * is a module -- see FBINFO_* in include/linux/fb.h
704f7018c21STomi Valkeinen *
705f7018c21STomi Valkeinen * If your hardware can support any of the hardware accelerated functions
706f7018c21STomi Valkeinen * fbcon performance will improve if info->flags is set properly.
707f7018c21STomi Valkeinen *
708f7018c21STomi Valkeinen * FBINFO_HWACCEL_COPYAREA - hardware moves
709f7018c21STomi Valkeinen * FBINFO_HWACCEL_FILLRECT - hardware fills
710f7018c21STomi Valkeinen * FBINFO_HWACCEL_IMAGEBLIT - hardware mono->color expansion
711f7018c21STomi Valkeinen * FBINFO_HWACCEL_YPAN - hardware can pan display in y-axis
712f7018c21STomi Valkeinen * FBINFO_HWACCEL_YWRAP - hardware can wrap display in y-axis
713f7018c21STomi Valkeinen * FBINFO_HWACCEL_DISABLED - supports hardware accels, but disabled
714f7018c21STomi Valkeinen * FBINFO_READS_FAST - if set, prefer moves over mono->color expansion
715f7018c21STomi Valkeinen * FBINFO_MISC_TILEBLITTING - hardware can do tile blits
716f7018c21STomi Valkeinen *
717f7018c21STomi Valkeinen * NOTE: These are for fbcon use only.
718f7018c21STomi Valkeinen */
719*b3e148d7SThomas Zimmermann info->flags = 0;
720f7018c21STomi Valkeinen
721f7018c21STomi Valkeinen /********************* This stage is optional ******************************/
722f7018c21STomi Valkeinen /*
723f7018c21STomi Valkeinen * The struct pixmap is a scratch pad for the drawing functions. This
724f7018c21STomi Valkeinen * is where the monochrome bitmap is constructed by the higher layers
725f7018c21STomi Valkeinen * and then passed to the accelerator. For drivers that uses
726f7018c21STomi Valkeinen * cfb_imageblit, you can skip this part. For those that have a more
727f7018c21STomi Valkeinen * rigorous requirement, this stage is needed
728f7018c21STomi Valkeinen */
729f7018c21STomi Valkeinen
730f7018c21STomi Valkeinen /* PIXMAP_SIZE should be small enough to optimize drawing, but not
731f7018c21STomi Valkeinen * large enough that memory is wasted. A safe size is
732f7018c21STomi Valkeinen * (max_xres * max_font_height/8). max_xres is driver dependent,
733f7018c21STomi Valkeinen * max_font_height is 32.
734f7018c21STomi Valkeinen */
735f7018c21STomi Valkeinen info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL);
736f7018c21STomi Valkeinen if (!info->pixmap.addr) {
737f7018c21STomi Valkeinen /* goto error */
738f7018c21STomi Valkeinen }
739f7018c21STomi Valkeinen
740f7018c21STomi Valkeinen info->pixmap.size = PIXMAP_SIZE;
741f7018c21STomi Valkeinen
742f7018c21STomi Valkeinen /*
743f7018c21STomi Valkeinen * FB_PIXMAP_SYSTEM - memory is in system ram
744f7018c21STomi Valkeinen * FB_PIXMAP_IO - memory is iomapped
745f7018c21STomi Valkeinen * FB_PIXMAP_SYNC - if set, will call fb_sync() per access to pixmap,
746f7018c21STomi Valkeinen * usually if FB_PIXMAP_IO is set.
747f7018c21STomi Valkeinen *
748f7018c21STomi Valkeinen * Currently, FB_PIXMAP_IO is unimplemented.
749f7018c21STomi Valkeinen */
750f7018c21STomi Valkeinen info->pixmap.flags = FB_PIXMAP_SYSTEM;
751f7018c21STomi Valkeinen
752f7018c21STomi Valkeinen /*
753f7018c21STomi Valkeinen * scan_align is the number of padding for each scanline. It is in bytes.
754f7018c21STomi Valkeinen * Thus for accelerators that need padding to the next u32, put 4 here.
755f7018c21STomi Valkeinen */
756f7018c21STomi Valkeinen info->pixmap.scan_align = 4;
757f7018c21STomi Valkeinen
758f7018c21STomi Valkeinen /*
759f7018c21STomi Valkeinen * buf_align is the amount to be padded for the buffer. For example,
760f7018c21STomi Valkeinen * the i810fb needs a scan_align of 2 but expects it to be fed with
761f7018c21STomi Valkeinen * dwords, so a buf_align = 4 is required.
762f7018c21STomi Valkeinen */
763f7018c21STomi Valkeinen info->pixmap.buf_align = 4;
764f7018c21STomi Valkeinen
765f7018c21STomi Valkeinen /* access_align is how many bits can be accessed from the framebuffer
766f7018c21STomi Valkeinen * ie. some epson cards allow 16-bit access only. Most drivers will
767f7018c21STomi Valkeinen * be safe with u32 here.
768f7018c21STomi Valkeinen *
769f7018c21STomi Valkeinen * NOTE: This field is currently unused.
770f7018c21STomi Valkeinen */
771f7018c21STomi Valkeinen info->pixmap.access_align = 32;
772f7018c21STomi Valkeinen /***************************** End optional stage ***************************/
773f7018c21STomi Valkeinen
774f7018c21STomi Valkeinen /*
775f7018c21STomi Valkeinen * This should give a reasonable default video mode. The following is
776f7018c21STomi Valkeinen * done when we can set a video mode.
777f7018c21STomi Valkeinen */
778f7018c21STomi Valkeinen if (!mode_option)
779f7018c21STomi Valkeinen mode_option = "640x480@60";
780f7018c21STomi Valkeinen
781f7018c21STomi Valkeinen retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
782f7018c21STomi Valkeinen
783f7018c21STomi Valkeinen if (!retval || retval == 4)
784f7018c21STomi Valkeinen return -EINVAL;
785f7018c21STomi Valkeinen
786f7018c21STomi Valkeinen /* This has to be done! */
787f7018c21STomi Valkeinen if (fb_alloc_cmap(&info->cmap, cmap_len, 0))
788f7018c21STomi Valkeinen return -ENOMEM;
789f7018c21STomi Valkeinen
790f7018c21STomi Valkeinen /*
791f7018c21STomi Valkeinen * The following is done in the case of having hardware with a static
792f7018c21STomi Valkeinen * mode. If we are setting the mode ourselves we don't call this.
793f7018c21STomi Valkeinen */
794f7018c21STomi Valkeinen info->var = xxxfb_var;
795f7018c21STomi Valkeinen
796f7018c21STomi Valkeinen /*
797f7018c21STomi Valkeinen * For drivers that can...
798f7018c21STomi Valkeinen */
799f7018c21STomi Valkeinen xxxfb_check_var(&info->var, info);
800f7018c21STomi Valkeinen
801f7018c21STomi Valkeinen /*
802f7018c21STomi Valkeinen * Does a call to fb_set_par() before register_framebuffer needed? This
803f7018c21STomi Valkeinen * will depend on you and the hardware. If you are sure that your driver
804f7018c21STomi Valkeinen * is the only device in the system, a call to fb_set_par() is safe.
805f7018c21STomi Valkeinen *
806f7018c21STomi Valkeinen * Hardware in x86 systems has a VGA core. Calling set_par() at this
807f7018c21STomi Valkeinen * point will corrupt the VGA console, so it might be safer to skip a
808f7018c21STomi Valkeinen * call to set_par here and just allow fbcon to do it for you.
809f7018c21STomi Valkeinen */
810f7018c21STomi Valkeinen /* xxxfb_set_par(info); */
811f7018c21STomi Valkeinen
812f7018c21STomi Valkeinen if (register_framebuffer(info) < 0) {
813f7018c21STomi Valkeinen fb_dealloc_cmap(&info->cmap);
814f7018c21STomi Valkeinen return -EINVAL;
815f7018c21STomi Valkeinen }
816f7018c21STomi Valkeinen fb_info(info, "%s frame buffer device\n", info->fix.id);
817f7018c21STomi Valkeinen pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */
818f7018c21STomi Valkeinen return 0;
819f7018c21STomi Valkeinen }
820f7018c21STomi Valkeinen
821f7018c21STomi Valkeinen /*
822f7018c21STomi Valkeinen * Cleanup
823f7018c21STomi Valkeinen */
824f7018c21STomi Valkeinen /* static void xxxfb_remove(struct platform_device *pdev) */
xxxfb_remove(struct pci_dev * dev)825f7018c21STomi Valkeinen static void xxxfb_remove(struct pci_dev *dev)
826f7018c21STomi Valkeinen {
827f7018c21STomi Valkeinen struct fb_info *info = pci_get_drvdata(dev);
828f7018c21STomi Valkeinen /* or platform_get_drvdata(pdev); */
829f7018c21STomi Valkeinen
830f7018c21STomi Valkeinen if (info) {
831f7018c21STomi Valkeinen unregister_framebuffer(info);
832f7018c21STomi Valkeinen fb_dealloc_cmap(&info->cmap);
833f7018c21STomi Valkeinen /* ... */
834f7018c21STomi Valkeinen framebuffer_release(info);
835f7018c21STomi Valkeinen }
836f7018c21STomi Valkeinen }
837f7018c21STomi Valkeinen
838f7018c21STomi Valkeinen #ifdef CONFIG_PCI
839f7018c21STomi Valkeinen #ifdef CONFIG_PM
840f7018c21STomi Valkeinen /**
841f7018c21STomi Valkeinen * xxxfb_suspend - Optional but recommended function. Suspend the device.
842f7018c21STomi Valkeinen * @dev: PCI device
843f7018c21STomi Valkeinen * @msg: the suspend event code.
844f7018c21STomi Valkeinen *
845ec15872dSMauro Carvalho Chehab * See Documentation/driver-api/pm/devices.rst for more information
846f7018c21STomi Valkeinen */
xxxfb_suspend(struct device * dev)847267173cbSBjorn Helgaas static int xxxfb_suspend(struct device *dev)
848f7018c21STomi Valkeinen {
849267173cbSBjorn Helgaas struct fb_info *info = dev_get_drvdata(dev);
850f7018c21STomi Valkeinen struct xxxfb_par *par = info->par;
851f7018c21STomi Valkeinen
852f7018c21STomi Valkeinen /* suspend here */
853f7018c21STomi Valkeinen return 0;
854f7018c21STomi Valkeinen }
855f7018c21STomi Valkeinen
856f7018c21STomi Valkeinen /**
857f7018c21STomi Valkeinen * xxxfb_resume - Optional but recommended function. Resume the device.
858f7018c21STomi Valkeinen * @dev: PCI device
859f7018c21STomi Valkeinen *
860ec15872dSMauro Carvalho Chehab * See Documentation/driver-api/pm/devices.rst for more information
861f7018c21STomi Valkeinen */
xxxfb_resume(struct device * dev)862267173cbSBjorn Helgaas static int xxxfb_resume(struct device *dev)
863f7018c21STomi Valkeinen {
864267173cbSBjorn Helgaas struct fb_info *info = dev_get_drvdata(dev);
865f7018c21STomi Valkeinen struct xxxfb_par *par = info->par;
866f7018c21STomi Valkeinen
867f7018c21STomi Valkeinen /* resume here */
868f7018c21STomi Valkeinen return 0;
869f7018c21STomi Valkeinen }
870f7018c21STomi Valkeinen #else
871f7018c21STomi Valkeinen #define xxxfb_suspend NULL
872f7018c21STomi Valkeinen #define xxxfb_resume NULL
873f7018c21STomi Valkeinen #endif /* CONFIG_PM */
874f7018c21STomi Valkeinen
8759271bc0fSArvind Yadav static const struct pci_device_id xxxfb_id_table[] = {
876f7018c21STomi Valkeinen { PCI_VENDOR_ID_XXX, PCI_DEVICE_ID_XXX,
877f7018c21STomi Valkeinen PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
878f7018c21STomi Valkeinen PCI_CLASS_MASK, 0 },
879f7018c21STomi Valkeinen { 0, }
880f7018c21STomi Valkeinen };
881f7018c21STomi Valkeinen
882267173cbSBjorn Helgaas static SIMPLE_DEV_PM_OPS(xxxfb_pm_ops, xxxfb_suspend, xxxfb_resume);
883267173cbSBjorn Helgaas
884f7018c21STomi Valkeinen /* For PCI drivers */
885f7018c21STomi Valkeinen static struct pci_driver xxxfb_driver = {
886f7018c21STomi Valkeinen .name = "xxxfb",
887f7018c21STomi Valkeinen .id_table = xxxfb_id_table,
888f7018c21STomi Valkeinen .probe = xxxfb_probe,
889f7018c21STomi Valkeinen .remove = xxxfb_remove,
890267173cbSBjorn Helgaas .driver.pm = xxxfb_pm_ops, /* optional but recommended */
891f7018c21STomi Valkeinen };
892f7018c21STomi Valkeinen
893f7018c21STomi Valkeinen MODULE_DEVICE_TABLE(pci, xxxfb_id_table);
894f7018c21STomi Valkeinen
xxxfb_init(void)8956a7d270eSGeert Uytterhoeven static int __init xxxfb_init(void)
896f7018c21STomi Valkeinen {
897f7018c21STomi Valkeinen /*
898f7018c21STomi Valkeinen * For kernel boot options (in 'video=xxxfb:<options>' format)
899f7018c21STomi Valkeinen */
900f7018c21STomi Valkeinen #ifndef MODULE
901f7018c21STomi Valkeinen char *option = NULL;
902f7018c21STomi Valkeinen
903f7018c21STomi Valkeinen if (fb_get_options("xxxfb", &option))
904f7018c21STomi Valkeinen return -ENODEV;
905f7018c21STomi Valkeinen xxxfb_setup(option);
906f7018c21STomi Valkeinen #endif
907f7018c21STomi Valkeinen
908f7018c21STomi Valkeinen return pci_register_driver(&xxxfb_driver);
909f7018c21STomi Valkeinen }
910f7018c21STomi Valkeinen
xxxfb_exit(void)911f7018c21STomi Valkeinen static void __exit xxxfb_exit(void)
912f7018c21STomi Valkeinen {
913f7018c21STomi Valkeinen pci_unregister_driver(&xxxfb_driver);
914f7018c21STomi Valkeinen }
915f7018c21STomi Valkeinen #else /* non PCI, platform drivers */
916f7018c21STomi Valkeinen #include <linux/platform_device.h>
917f7018c21STomi Valkeinen /* for platform devices */
918f7018c21STomi Valkeinen
919f7018c21STomi Valkeinen #ifdef CONFIG_PM
920f7018c21STomi Valkeinen /**
921f7018c21STomi Valkeinen * xxxfb_suspend - Optional but recommended function. Suspend the device.
922f7018c21STomi Valkeinen * @dev: platform device
923f7018c21STomi Valkeinen * @msg: the suspend event code.
924f7018c21STomi Valkeinen *
925ec15872dSMauro Carvalho Chehab * See Documentation/driver-api/pm/devices.rst for more information
926f7018c21STomi Valkeinen */
xxxfb_suspend(struct platform_device * dev,pm_message_t msg)927f7018c21STomi Valkeinen static int xxxfb_suspend(struct platform_device *dev, pm_message_t msg)
928f7018c21STomi Valkeinen {
929f7018c21STomi Valkeinen struct fb_info *info = platform_get_drvdata(dev);
930f7018c21STomi Valkeinen struct xxxfb_par *par = info->par;
931f7018c21STomi Valkeinen
932f7018c21STomi Valkeinen /* suspend here */
933f7018c21STomi Valkeinen return 0;
934f7018c21STomi Valkeinen }
935f7018c21STomi Valkeinen
936f7018c21STomi Valkeinen /**
937f7018c21STomi Valkeinen * xxxfb_resume - Optional but recommended function. Resume the device.
938f7018c21STomi Valkeinen * @dev: platform device
939f7018c21STomi Valkeinen *
940ec15872dSMauro Carvalho Chehab * See Documentation/driver-api/pm/devices.rst for more information
941f7018c21STomi Valkeinen */
xxxfb_resume(struct platform_dev * dev)942f7018c21STomi Valkeinen static int xxxfb_resume(struct platform_dev *dev)
943f7018c21STomi Valkeinen {
944f7018c21STomi Valkeinen struct fb_info *info = platform_get_drvdata(dev);
945f7018c21STomi Valkeinen struct xxxfb_par *par = info->par;
946f7018c21STomi Valkeinen
947f7018c21STomi Valkeinen /* resume here */
948f7018c21STomi Valkeinen return 0;
949f7018c21STomi Valkeinen }
950f7018c21STomi Valkeinen #else
951f7018c21STomi Valkeinen #define xxxfb_suspend NULL
952f7018c21STomi Valkeinen #define xxxfb_resume NULL
953f7018c21STomi Valkeinen #endif /* CONFIG_PM */
954f7018c21STomi Valkeinen
955f7018c21STomi Valkeinen static struct platform_device_driver xxxfb_driver = {
956f7018c21STomi Valkeinen .probe = xxxfb_probe,
957f7018c21STomi Valkeinen .remove = xxxfb_remove,
958f7018c21STomi Valkeinen .suspend = xxxfb_suspend, /* optional but recommended */
959f7018c21STomi Valkeinen .resume = xxxfb_resume, /* optional but recommended */
960f7018c21STomi Valkeinen .driver = {
961f7018c21STomi Valkeinen .name = "xxxfb",
962f7018c21STomi Valkeinen },
963f7018c21STomi Valkeinen };
964f7018c21STomi Valkeinen
965f7018c21STomi Valkeinen static struct platform_device *xxxfb_device;
966f7018c21STomi Valkeinen
967f7018c21STomi Valkeinen #ifndef MODULE
968f7018c21STomi Valkeinen /*
969f7018c21STomi Valkeinen * Setup
970f7018c21STomi Valkeinen */
971f7018c21STomi Valkeinen
972f7018c21STomi Valkeinen /*
973f7018c21STomi Valkeinen * Only necessary if your driver takes special options,
974f7018c21STomi Valkeinen * otherwise we fall back on the generic fb_setup().
975f7018c21STomi Valkeinen */
xxxfb_setup(char * options)9766a7d270eSGeert Uytterhoeven static int __init xxxfb_setup(char *options)
977f7018c21STomi Valkeinen {
978f7018c21STomi Valkeinen /* Parse user specified options (`video=xxxfb:') */
979f7018c21STomi Valkeinen }
980f7018c21STomi Valkeinen #endif /* MODULE */
981f7018c21STomi Valkeinen
xxxfb_init(void)982f7018c21STomi Valkeinen static int __init xxxfb_init(void)
983f7018c21STomi Valkeinen {
984f7018c21STomi Valkeinen int ret;
985f7018c21STomi Valkeinen /*
986f7018c21STomi Valkeinen * For kernel boot options (in 'video=xxxfb:<options>' format)
987f7018c21STomi Valkeinen */
988f7018c21STomi Valkeinen #ifndef MODULE
989f7018c21STomi Valkeinen char *option = NULL;
9900ba2fa8cSThomas Zimmermann #endif
991f7018c21STomi Valkeinen
9920ba2fa8cSThomas Zimmermann if (fb_modesetting_disabled("xxxfb"))
9930ba2fa8cSThomas Zimmermann return -ENODEV;
9940ba2fa8cSThomas Zimmermann
9950ba2fa8cSThomas Zimmermann #ifndef MODULE
996f7018c21STomi Valkeinen if (fb_get_options("xxxfb", &option))
997f7018c21STomi Valkeinen return -ENODEV;
998f7018c21STomi Valkeinen xxxfb_setup(option);
999f7018c21STomi Valkeinen #endif
1000f7018c21STomi Valkeinen ret = platform_driver_register(&xxxfb_driver);
1001f7018c21STomi Valkeinen
1002f7018c21STomi Valkeinen if (!ret) {
1003f7018c21STomi Valkeinen xxxfb_device = platform_device_register_simple("xxxfb", 0,
1004f7018c21STomi Valkeinen NULL, 0);
1005f7018c21STomi Valkeinen
1006f7018c21STomi Valkeinen if (IS_ERR(xxxfb_device)) {
1007f7018c21STomi Valkeinen platform_driver_unregister(&xxxfb_driver);
1008f7018c21STomi Valkeinen ret = PTR_ERR(xxxfb_device);
1009f7018c21STomi Valkeinen }
1010f7018c21STomi Valkeinen }
1011f7018c21STomi Valkeinen
1012f7018c21STomi Valkeinen return ret;
1013f7018c21STomi Valkeinen }
1014f7018c21STomi Valkeinen
xxxfb_exit(void)1015f7018c21STomi Valkeinen static void __exit xxxfb_exit(void)
1016f7018c21STomi Valkeinen {
1017f7018c21STomi Valkeinen platform_device_unregister(xxxfb_device);
1018f7018c21STomi Valkeinen platform_driver_unregister(&xxxfb_driver);
1019f7018c21STomi Valkeinen }
1020f7018c21STomi Valkeinen #endif /* CONFIG_PCI */
1021f7018c21STomi Valkeinen
1022f7018c21STomi Valkeinen /* ------------------------------------------------------------------------- */
1023f7018c21STomi Valkeinen
1024f7018c21STomi Valkeinen
1025f7018c21STomi Valkeinen /*
1026f7018c21STomi Valkeinen * Modularization
1027f7018c21STomi Valkeinen */
1028f7018c21STomi Valkeinen
1029f7018c21STomi Valkeinen module_init(xxxfb_init);
1030f7018c21STomi Valkeinen module_exit(xxxfb_exit);
1031f7018c21STomi Valkeinen
1032f7018c21STomi Valkeinen MODULE_LICENSE("GPL");
1033