1 /*
2 * linux/drivers/video/fbcmap.c -- Colormap handling for frame buffer devices
3 *
4 * Created 15 Jun 1997 by Geert Uytterhoeven
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive for
8 * more details.
9 */
10
11 #include <linux/string.h>
12 #include <linux/module.h>
13 #include <linux/tty.h>
14 #include <linux/fb.h>
15 #include <linux/slab.h>
16
17 #include <asm/uaccess.h>
18
19 static u16 red2[] = {
20 0x0000, 0xaaaa
21 };
22 static u16 green2[] = {
23 0x0000, 0xaaaa
24 };
25 static u16 blue2[] = {
26 0x0000, 0xaaaa
27 };
28
29 static u16 red4[] = {
30 0x0000, 0xaaaa, 0x5555, 0xffff
31 };
32 static u16 green4[] = {
33 0x0000, 0xaaaa, 0x5555, 0xffff
34 };
35 static u16 blue4[] = {
36 0x0000, 0xaaaa, 0x5555, 0xffff
37 };
38
39 static u16 red8[] = {
40 0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa
41 };
42 static u16 green8[] = {
43 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa
44 };
45 static u16 blue8[] = {
46 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa
47 };
48
49 static u16 red16[] = {
50 0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa,
51 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff
52 };
53 static u16 green16[] = {
54 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa,
55 0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff
56 };
57 static u16 blue16[] = {
58 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa,
59 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff
60 };
61
62 static struct fb_cmap default_2_colors = {
63 0, 2, red2, green2, blue2, NULL
64 };
65 static struct fb_cmap default_8_colors = {
66 0, 8, red8, green8, blue8, NULL
67 };
68 static struct fb_cmap default_4_colors = {
69 0, 4, red4, green4, blue4, NULL
70 };
71 static struct fb_cmap default_16_colors = {
72 0, 16, red16, green16, blue16, NULL
73 };
74
75
76 /*
77 * Allocate a colormap
78 */
79
80 int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
81 {
82 int size = len*sizeof(u16);
83
84 if (cmap->len != len) {
85 if (cmap->red)
86 kfree(cmap->red);
87 if (cmap->green)
88 kfree(cmap->green);
89 if (cmap->blue)
90 kfree(cmap->blue);
91 if (cmap->transp)
92 kfree(cmap->transp);
93 cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
94 cmap->len = 0;
95 if (!len)
96 return 0;
97 if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
98 return -1;
99 if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
100 return -1;
101 if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
102 return -1;
103 if (transp) {
104 if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
105 return -1;
106 } else
107 cmap->transp = NULL;
108 }
109 cmap->start = 0;
110 cmap->len = len;
111 fb_copy_cmap(fb_default_cmap(len), cmap, 0);
112 return 0;
113 }
114
115
116 /*
117 * Copy a colormap
118 */
119
120 void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
121 {
122 int size;
123 int tooff = 0, fromoff = 0;
124
125 if (to->start > from->start)
126 fromoff = to->start-from->start;
127 else
128 tooff = from->start-to->start;
129 size = to->len-tooff;
130 if (size > from->len-fromoff)
131 size = from->len-fromoff;
132 if (size < 0)
133 return;
134 size *= sizeof(u16);
135
136 switch (fsfromto) {
137 case 0:
138 memcpy(to->red+tooff, from->red+fromoff, size);
139 memcpy(to->green+tooff, from->green+fromoff, size);
140 memcpy(to->blue+tooff, from->blue+fromoff, size);
141 if (from->transp && to->transp)
142 memcpy(to->transp+tooff, from->transp+fromoff, size);
143 break;
144 case 1:
145 copy_from_user(to->red+tooff, from->red+fromoff, size);
146 copy_from_user(to->green+tooff, from->green+fromoff, size);
147 copy_from_user(to->blue+tooff, from->blue+fromoff, size);
148 if (from->transp && to->transp)
149 copy_from_user(to->transp+tooff, from->transp+fromoff, size);
150 break;
151 case 2:
152 copy_to_user(to->red+tooff, from->red+fromoff, size);
153 copy_to_user(to->green+tooff, from->green+fromoff, size);
154 copy_to_user(to->blue+tooff, from->blue+fromoff, size);
155 if (from->transp && to->transp)
156 copy_to_user(to->transp+tooff, from->transp+fromoff, size);
157 break;
158 }
159 }
160
161
162 /*
163 * Get the colormap for a screen
164 */
165
166 int fb_get_cmap(struct fb_cmap *cmap, int kspc,
167 int (*getcolreg)(u_int, u_int *, u_int *, u_int *, u_int *,
168 struct fb_info *),
169 struct fb_info *info)
170 {
171 int i, start;
172 u16 *red, *green, *blue, *transp;
173 u_int hred, hgreen, hblue, htransp;
174
175 red = cmap->red;
176 green = cmap->green;
177 blue = cmap->blue;
178 transp = cmap->transp;
179 start = cmap->start;
180 if (start < 0)
181 return -EINVAL;
182 for (i = 0; i < cmap->len; i++) {
183 if (getcolreg(start++, &hred, &hgreen, &hblue, &htransp, info))
184 return 0;
185 if (kspc) {
186 *red = hred;
187 *green = hgreen;
188 *blue = hblue;
189 if (transp)
190 *transp = htransp;
191 } else {
192 put_user(hred, red);
193 put_user(hgreen, green);
194 put_user(hblue, blue);
195 if (transp)
196 put_user(htransp, transp);
197 }
198 red++;
199 green++;
200 blue++;
201 if (transp)
202 transp++;
203 }
204 return 0;
205 }
206
207
208 /*
209 * Set the colormap for a screen
210 */
211
212 int fb_set_cmap(struct fb_cmap *cmap, int kspc,
213 int (*setcolreg)(u_int, u_int, u_int, u_int, u_int,
214 struct fb_info *),
215 struct fb_info *info)
216 {
217 int i, start;
218 u16 *red, *green, *blue, *transp;
219 u_int hred, hgreen, hblue, htransp;
220
221 red = cmap->red;
222 green = cmap->green;
223 blue = cmap->blue;
224 transp = cmap->transp;
225 start = cmap->start;
226
227 if (start < 0)
228 return -EINVAL;
229 for (i = 0; i < cmap->len; i++) {
230 if (kspc) {
231 hred = *red;
232 hgreen = *green;
233 hblue = *blue;
234 htransp = transp ? *transp : 0;
235 } else {
236 get_user(hred, red);
237 get_user(hgreen, green);
238 get_user(hblue, blue);
239 if (transp)
240 get_user(htransp, transp);
241 else
242 htransp = 0;
243 }
244 red++;
245 green++;
246 blue++;
247 if (transp)
248 transp++;
249 if (setcolreg(start++, hred, hgreen, hblue, htransp, info))
250 return 0;
251 }
252 return 0;
253 }
254
255
256 /*
257 * Get the default colormap for a specific screen depth
258 */
259
260 struct fb_cmap *fb_default_cmap(int len)
261 {
262 if (len <= 2)
263 return &default_2_colors;
264 if (len <= 4)
265 return &default_4_colors;
266 if (len <= 8)
267 return &default_8_colors;
268 return &default_16_colors;
269 }
270
271
272 /*
273 * Invert all default colormaps
274 */
275
276 void fb_invert_cmaps(void)
277 {
278 u_int i;
279
280 for (i = 0; i < 2; i++) {
281 red2[i] = ~red2[i];
282 green2[i] = ~green2[i];
283 blue2[i] = ~blue2[i];
284 }
285 for (i = 0; i < 4; i++) {
286 red4[i] = ~red4[i];
287 green4[i] = ~green4[i];
288 blue4[i] = ~blue4[i];
289 }
290 for (i = 0; i < 8; i++) {
291 red8[i] = ~red8[i];
292 green8[i] = ~green8[i];
293 blue8[i] = ~blue8[i];
294 }
295 for (i = 0; i < 16; i++) {
296 red16[i] = ~red16[i];
297 green16[i] = ~green16[i];
298 blue16[i] = ~blue16[i];
299 }
300 }
301
302
303 /*
304 * Visible symbols for modules
305 */
306
307 EXPORT_SYMBOL(fb_alloc_cmap);
308 EXPORT_SYMBOL(fb_copy_cmap);
309 EXPORT_SYMBOL(fb_get_cmap);
310 EXPORT_SYMBOL(fb_set_cmap);
311 EXPORT_SYMBOL(fb_default_cmap);
312 EXPORT_SYMBOL(fb_invert_cmaps);
313
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.