make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / drivers / video / fbcmap.c
1 /*
2  *  linux/drivers/video/fbcmap.c -- Colormap handling for frame buffer devices
3  *
4  *      Created 15 Jun 1997 by Geert Uytterhoeven
5  *
6  *      2001 - Documented with DocBook
7  *      - Brad Douglas <brad@neruo.com>
8  *
9  *  This file is subject to the terms and conditions of the GNU General Public
10  *  License.  See the file COPYING in the main directory of this archive for
11  *  more details.
12  */
13
14 #include <linux/string.h>
15 #include <linux/module.h>
16 #include <linux/tty.h>
17 #include <linux/fb.h>
18 #include <linux/slab.h>
19
20 #include <asm/uaccess.h>
21
22 static u16 red2[] = {
23     0x0000, 0xaaaa
24 };
25 static u16 green2[] = {
26     0x0000, 0xaaaa
27 };
28 static u16 blue2[] = {
29     0x0000, 0xaaaa
30 };
31
32 static u16 red4[] = {
33     0x0000, 0xaaaa, 0x5555, 0xffff
34 };
35 static u16 green4[] = {
36     0x0000, 0xaaaa, 0x5555, 0xffff
37 };
38 static u16 blue4[] = {
39     0x0000, 0xaaaa, 0x5555, 0xffff
40 };
41
42 static u16 red8[] = {
43     0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa
44 };
45 static u16 green8[] = {
46     0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa
47 };
48 static u16 blue8[] = {
49     0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa
50 };
51
52 static u16 red16[] = {
53     0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa,
54     0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff
55 };
56 static u16 green16[] = {
57     0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa,
58     0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff
59 };
60 static u16 blue16[] = {
61     0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa,
62     0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff
63 };
64
65 static struct fb_cmap default_2_colors = {
66     0, 2, red2, green2, blue2, NULL
67 };
68 static struct fb_cmap default_8_colors = {
69     0, 8, red8, green8, blue8, NULL
70 };
71 static struct fb_cmap default_4_colors = {
72     0, 4, red4, green4, blue4, NULL
73 };
74 static struct fb_cmap default_16_colors = {
75     0, 16, red16, green16, blue16, NULL
76 };
77
78
79 /**
80  *      fb_alloc_cmap - allocate a colormap
81  *      @cmap: frame buffer colormap structure
82  *      @len: length of @cmap
83  *      @transp: boolean, 1 if there is transparency, 0 otherwise
84  *
85  *      Allocates memory for a colormap @cmap.  @len is the
86  *      number of entries in the palette.
87  *
88  *      Returns -1 errno on error, or zero on success.
89  *
90  */
91
92 int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
93 {
94     int size = len*sizeof(u16);
95
96     if (cmap->len != len) {
97         if (cmap->red)
98             kfree(cmap->red);
99         if (cmap->green)
100             kfree(cmap->green);
101         if (cmap->blue)
102             kfree(cmap->blue);
103         if (cmap->transp)
104             kfree(cmap->transp);
105         cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
106         cmap->len = 0;
107         if (!len)
108             return 0;
109         if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
110             return -1;
111         if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
112             return -1;
113         if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
114             return -1;
115         if (transp) {
116             if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
117                 return -1;
118         } else
119             cmap->transp = NULL;
120     }
121     cmap->start = 0;
122     cmap->len = len;
123     fb_copy_cmap(fb_default_cmap(len), cmap, 0);
124     return 0;
125 }
126
127
128 /**
129  *      fb_copy_cmap - copy a colormap
130  *      @from: frame buffer colormap structure
131  *      @to: frame buffer colormap structure
132  *      @fsfromto: determine copy method
133  *
134  *      Copy contents of colormap from @from to @to.
135  *
136  *      @fsfromto accepts the following integer parameters:
137  *      0: memcpy function
138  *      1: copy_from_user() function to copy from userspace
139  *      2: copy_to_user() function to copy to userspace
140  *
141  */
142
143 void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
144 {
145     int size;
146     int tooff = 0, fromoff = 0;
147
148     if (to->start > from->start)
149         fromoff = to->start-from->start;
150     else
151         tooff = from->start-to->start;
152     size = to->len-tooff;
153     if (size > from->len-fromoff)
154         size = from->len-fromoff;
155     if (size < 0)
156         return;
157     size *= sizeof(u16);
158     
159     switch (fsfromto) {
160     case 0:
161         memcpy(to->red+tooff, from->red+fromoff, size);
162         memcpy(to->green+tooff, from->green+fromoff, size);
163         memcpy(to->blue+tooff, from->blue+fromoff, size);
164         if (from->transp && to->transp)
165             memcpy(to->transp+tooff, from->transp+fromoff, size);
166         break;
167     case 1:
168         copy_from_user(to->red+tooff, from->red+fromoff, size);
169         copy_from_user(to->green+tooff, from->green+fromoff, size);
170         copy_from_user(to->blue+tooff, from->blue+fromoff, size);
171         if (from->transp && to->transp)
172             copy_from_user(to->transp+tooff, from->transp+fromoff, size);
173         break;
174     case 2:
175         copy_to_user(to->red+tooff, from->red+fromoff, size);
176         copy_to_user(to->green+tooff, from->green+fromoff, size);
177         copy_to_user(to->blue+tooff, from->blue+fromoff, size);
178         if (from->transp && to->transp)
179             copy_to_user(to->transp+tooff, from->transp+fromoff, size);
180         break;
181     }
182 }
183
184
185 /**
186  *      fb_get_cmap - get a colormap
187  *      @cmap: frame buffer colormap
188  *      @kspc: boolean, 0 copy local, 1 put_user() function
189  *      @getcolreg: pointer to a function to get a color register
190  *      @info: frame buffer info structure
191  *
192  *      Get a colormap @cmap for a screen of device @info.
193  *
194  *      Returns negative errno on error, or zero on success.
195  *
196  */
197
198 int fb_get_cmap(struct fb_cmap *cmap, int kspc,
199                 int (*getcolreg)(u_int, u_int *, u_int *, u_int *, u_int *,
200                                  struct fb_info *),
201                 struct fb_info *info)
202 {
203     int i, start;
204     u16 *red, *green, *blue, *transp;
205     u_int hred, hgreen, hblue, htransp;
206
207     red = cmap->red;
208     green = cmap->green;
209     blue = cmap->blue;
210     transp = cmap->transp;
211     start = cmap->start;
212     if (start < 0)
213         return -EINVAL;
214     for (i = 0; i < cmap->len; i++) {
215         if (getcolreg(start++, &hred, &hgreen, &hblue, &htransp, info))
216             return 0;
217         if (kspc) {
218             *red = hred;
219             *green = hgreen;
220             *blue = hblue;
221             if (transp)
222                 *transp = htransp;
223         } else {
224             put_user(hred, red);
225             put_user(hgreen, green);
226             put_user(hblue, blue);
227             if (transp)
228                 put_user(htransp, transp);
229         }
230         red++;
231         green++;
232         blue++;
233         if (transp)
234             transp++;
235     }
236     return 0;
237 }
238
239
240 /**
241  *      fb_set_cmap - set the colormap
242  *      @cmap: frame buffer colormap structure
243  *      @kspc: boolean, 0 copy local, 1 get_user() function
244  *      @info: frame buffer info structure
245  *
246  *      Sets the colormap @cmap for a screen of device @info.
247  *
248  *      Returns negative errno on error, or zero on success.
249  *
250  */
251
252 int fb_set_cmap(struct fb_cmap *cmap, int kspc,
253                 int (*setcolreg)(u_int, u_int, u_int, u_int, u_int,
254                                  struct fb_info *),
255                 struct fb_info *info)
256 {
257     int i, start;
258     u16 *red, *green, *blue, *transp;
259     u_int hred, hgreen, hblue, htransp;
260
261     red = cmap->red;
262     green = cmap->green;
263     blue = cmap->blue;
264     transp = cmap->transp;
265     start = cmap->start;
266
267     if (start < 0)
268         return -EINVAL;
269     for (i = 0; i < cmap->len; i++) {
270         if (kspc) {
271             hred = *red;
272             hgreen = *green;
273             hblue = *blue;
274             htransp = transp ? *transp : 0;
275         } else {
276             get_user(hred, red);
277             get_user(hgreen, green);
278             get_user(hblue, blue);
279             if (transp)
280                 get_user(htransp, transp);
281             else
282                 htransp = 0;
283         }
284         red++;
285         green++;
286         blue++;
287         if (transp)
288             transp++;
289         if (setcolreg(start++, hred, hgreen, hblue, htransp, info))
290             return 0;
291     }
292     return 0;
293 }
294
295
296 /**
297  *      fb_default_cmap - get default colormap
298  *      @len: size of palette for a depth
299  *
300  *      Gets the default colormap for a specific screen depth.  @len
301  *      is the size of the palette for a particular screen depth.
302  *
303  *      Returns pointer to a frame buffer colormap structure.
304  *
305  */
306
307 struct fb_cmap *fb_default_cmap(int len)
308 {
309     if (len <= 2)
310         return &default_2_colors;
311     if (len <= 4)
312         return &default_4_colors;
313     if (len <= 8)
314         return &default_8_colors;
315     return &default_16_colors;
316 }
317
318
319 /**
320  *      fb_invert_cmaps - invert all defaults colormaps
321  *
322  *      Invert all default colormaps.
323  *
324  */
325
326 void fb_invert_cmaps(void)
327 {
328     u_int i;
329
330     for (i = 0; i < 2; i++) {
331         red2[i] = ~red2[i];
332         green2[i] = ~green2[i];
333         blue2[i] = ~blue2[i];
334     }
335     for (i = 0; i < 4; i++) {
336         red4[i] = ~red4[i];
337         green4[i] = ~green4[i];
338         blue4[i] = ~blue4[i];
339     }
340     for (i = 0; i < 8; i++) {
341         red8[i] = ~red8[i];
342         green8[i] = ~green8[i];
343         blue8[i] = ~blue8[i];
344     }
345     for (i = 0; i < 16; i++) {
346         red16[i] = ~red16[i];
347         green16[i] = ~green16[i];
348         blue16[i] = ~blue16[i];
349     }
350 }
351
352
353     /*
354      *  Visible symbols for modules
355      */
356
357 EXPORT_SYMBOL(fb_alloc_cmap);
358 EXPORT_SYMBOL(fb_copy_cmap);
359 EXPORT_SYMBOL(fb_get_cmap);
360 EXPORT_SYMBOL(fb_set_cmap);
361 EXPORT_SYMBOL(fb_default_cmap);
362 EXPORT_SYMBOL(fb_invert_cmaps);