Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

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