linux lcd驱动
时间:2010-04-21 来源:wulinnm
fbmem源代码:
1 /* 2 * linux/drivers/video/fbmem.c
3 *
4 * Copyright (C) 1994 Martin Schaller
5 *
6 * 2001 - Documented with DocBook
7 * - Brad Douglas <[email protected]>
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
11 * for more details.
12 */
13
14 #include <linux/module.h>
15
16 #include <linux/compat.h>
17 #include <linux/types.h>
18 #include <linux/errno.h>
19 #include <linux/smp_lock.h>
20 #include <linux/kernel.h>
21 #include <linux/major.h>
22 #include <linux/slab.h>
23 #include <linux/mm.h>
24 #include <linux/mman.h>
25 #include <linux/vt.h>
26 #include <linux/init.h>
27 #include <linux/linux_logo.h>
28 #include <linux/proc_fs.h>
29 #include <linux/console.h>
30 #ifdef CONFIG_KMOD
31 #include <linux/kmod.h>
32 #endif
33 #include <linux/err.h>
34 #include <linux/device.h>
35 #include <linux/efi.h>
36 #include <linux/fb.h>
37
38 #include <asm/fb.h>
39
40
41 /*
42 * Frame buffer device initialization and setup routines
43 */
44
45 #define FBPIXMAPSIZE (1024 * 8)
46
47 struct fb_info *registered_fb[FB_MAX] __read_mostly;
48 int num_registered_fb __read_mostly;
49
50 /*
51 * Helpers
52 */
53
54 int fb_get_color_depth(struct fb_var_screeninfo *var,
55 struct fb_fix_screeninfo *fix)
56 {
57 int depth = 0;
58
59 if (fix->visual == FB_VISUAL_MONO01 ||
60 fix->visual == FB_VISUAL_MONO10)
61 depth = 1;
62 else {
63 if (var->green.length == var->blue.length &&
64 var->green.length == var->red.length &&
65 var->green.offset == var->blue.offset &&
66 var->green.offset == var->red.offset)
67 depth = var->green.length;
68 else
69 depth = var->green.length + var->red.length +
70 var->blue.length;
71 }
72
73 return depth;
74 }
75 EXPORT_SYMBOL(fb_get_color_depth);
76
77 /*
78 * Data padding functions.
79 */
80 void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
81 {
82 __fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height);
83 }
84 EXPORT_SYMBOL(fb_pad_aligned_buffer);
85
86 void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height,
87 u32 shift_high, u32 shift_low, u32 mod)
88 {
89 u8 mask = (u8) (0xfff << shift_high), tmp;
90 int i, j;
91
92 for (i = height; i--; ) {
93 for (j = 0; j < idx; j++) {
94 tmp = dst[j];
95 tmp &= mask;
96 tmp |= *src >> shift_low;
97 dst[j] = tmp;
98 tmp = *src << shift_high;
99 dst[j+1] = tmp;
100 src++;
101 }
102 tmp = dst[idx];
103 tmp &= mask;
104 tmp |= *src >> shift_low;
105 dst[idx] = tmp;
106 if (shift_high < mod) {
107 tmp = *src << shift_high;
108 dst[idx+1] = tmp;
109 }
110 src++;
111 dst += d_pitch;
112 }
113 }
114 EXPORT_SYMBOL(fb_pad_unaligned_buffer);
115
116 /*
117 * we need to lock this section since fb_cursor
118 * may use fb_imageblit()
119 */
120 char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size)
121 {
122 u32 align = buf->buf_align - 1, offset;
123 char *addr = buf->addr;
124
125 /* If IO mapped, we need to sync before access, no sharing of
126 * the pixmap is done
127 */
128 if (buf->flags & FB_PIXMAP_IO) {
129 if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
130 info->fbops->fb_sync(info);
131 return addr;
132 }
133
134 /* See if we fit in the remaining pixmap space */
135 offset = buf->offset + align;
136 offset &= ~align;
137 if (offset + size > buf->size) {
138 /* We do not fit. In order to be able to re-use the buffer,
139 * we must ensure no asynchronous DMA'ing or whatever operation
140 * is in progress, we sync for that.
141 */
142 if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
143 info->fbops->fb_sync(info);
144 offset = 0;
145 }
146 buf->offset = offset + size;
147 addr += offset;
148
149 return addr;
150 }
151
152 #ifdef CONFIG_LOGO
153
154 static inline unsigned safe_shift(unsigned d, int n)
155 {
156 return n < 0 ? d >> -n : d << n;
157 }
158
159 static void fb_set_logocmap(struct fb_info *info,
160 const struct linux_logo *logo)
161 {
162 struct fb_cmap palette_cmap;
163 u16 palette_green[16];
164 u16 palette_blue[16];
165 u16 palette_red[16];
166 int i, j, n;
167 const unsigned char *clut = logo->clut;
168
169 palette_cmap.start = 0;
170 palette_cmap.len = 16;
171 palette_cmap.red = palette_red;
172 palette_cmap.green = palette_green;
173 palette_cmap.blue = palette_blue;
174 palette_cmap.transp = NULL;
175
176 for (i = 0; i < logo->clutsize; i += n) {
177 n = logo->clutsize - i;
178 /* palette_cmap provides space for only 16 colors at once */
179 if (n > 16)
180 n = 16;
181 palette_cmap.start = 32 + i;
182 palette_cmap.len = n;
183 for (j = 0; j < n; ++j) {
184 palette_cmap.red[j] = clut[0] << 8 | clut[0];
185 palette_cmap.green[j] = clut[1] << 8 | clut[1];
186 palette_cmap.blue[j] = clut[2] << 8 | clut[2];
187 clut += 3;
188 }
189 fb_set_cmap(&palette_cmap, info);
190 }
191 }
192
193 static void fb_set_logo_truepalette(struct fb_info *info,
194 const struct linux_logo *logo,
195 u32 *palette)
196 {
197 static const unsigned char mask[] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
198 unsigned char redmask, greenmask, bluemask;
199 int redshift, greenshift, blueshift;
200 int i;
201 const unsigned char *clut = logo->clut;
202
203 /*
204 * We have to create a temporary palette since console palette is only
205 * 16 colors long.
206 */
207 /* Bug: Doesn't obey msb_right ... (who needs that?) */
208 redmask = mask[info->var.red.length < 8 ? info->var.red.length : 8];
209 greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
210 bluemask = mask[info->var.blue.length < 8 ? info->var.blue.length : 8];
211 redshift = info->var.red.offset - (8 - info->var.red.length);
212 greenshift = info->var.green.offset - (8 - info->var.green.length);
213 blueshift = info->var.blue.offset - (8 - info->var.blue.length);
214
215 for ( i = 0; i < logo->clutsize; i++) {
216 palette[i+32] = (safe_shift((clut[0] & redmask), redshift) |
217 safe_shift((clut[1] & greenmask), greenshift) |
218 safe_shift((clut[2] & bluemask), blueshift));
219 clut += 3;
220 }
221 }
222
223 static void fb_set_logo_directpalette(struct fb_info *info,
224 const struct linux_logo *logo,
225 u32 *palette)
226 {
227 int redshift, greenshift, blueshift;
228 int i;
229
230 redshift = info->var.red.offset;
231 greenshift = info->var.green.offset;
232 blueshift = info->var.blue.offset;
233
234 for (i = 32; i < logo->clutsize; i++)
235 palette[i] = i << redshift | i << greenshift | i << blueshift;
236 }
237
238 static void fb_set_logo(struct fb_info *info,
239 const struct linux_logo *logo, u8 *dst,
240 int depth)
241 {
242 int i, j, k;
243 const u8 *src = logo->data;
244 u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
245 u8 fg = 1, d;
246
247 switch (fb_get_color_depth(&info->var, &info->fix)) {
248 case 1:
249 fg = 1;
250 break;
251 case 2:
252 fg = 3;
253 break;
254 default:
255 fg = 7;
256 break;
257 }
258
259 if (info->fix.visual == FB_VISUAL_MONO01 ||
260 info->fix.visual == FB_VISUAL_MONO10)
261 fg = ~((u8) (0xfff << info->var.green.length));
262
263 switch (depth) {
264 case 4:
265 for (i = 0; i < logo->height; i++)
266 for (j = 0; j < logo->width; src++) {
267 *dst++ = *src >> 4;
268 j++;
269 if (j < logo->width) {
270 *dst++ = *src & 0x0f;
271 j++;
272 }
273 }
274 break;
275 case 1:
276 for (i = 0; i < logo->height; i++) {
277 for (j = 0; j < logo->width; src++) {
278 d = *src ^ xor;
279 for (k = 7; k >= 0; k--) {
280 *dst++ = ((d >> k) & 1) ? fg : 0;
281 j++;
282 }
283 }
284 }
285 break;
286 }
287 }
3 *
4 * Copyright (C) 1994 Martin Schaller
5 *
6 * 2001 - Documented with DocBook
7 * - Brad Douglas <[email protected]>
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
11 * for more details.
12 */
13
14 #include <linux/module.h>
15
16 #include <linux/compat.h>
17 #include <linux/types.h>
18 #include <linux/errno.h>
19 #include <linux/smp_lock.h>
20 #include <linux/kernel.h>
21 #include <linux/major.h>
22 #include <linux/slab.h>
23 #include <linux/mm.h>
24 #include <linux/mman.h>
25 #include <linux/vt.h>
26 #include <linux/init.h>
27 #include <linux/linux_logo.h>
28 #include <linux/proc_fs.h>
29 #include <linux/console.h>
30 #ifdef CONFIG_KMOD
31 #include <linux/kmod.h>
32 #endif
33 #include <linux/err.h>
34 #include <linux/device.h>
35 #include <linux/efi.h>
36 #include <linux/fb.h>
37
38 #include <asm/fb.h>
39
40
41 /*
42 * Frame buffer device initialization and setup routines
43 */
44
45 #define FBPIXMAPSIZE (1024 * 8)
46
47 struct fb_info *registered_fb[FB_MAX] __read_mostly;
48 int num_registered_fb __read_mostly;
49
50 /*
51 * Helpers
52 */
53
54 int fb_get_color_depth(struct fb_var_screeninfo *var,
55 struct fb_fix_screeninfo *fix)
56 {
57 int depth = 0;
58
59 if (fix->visual == FB_VISUAL_MONO01 ||
60 fix->visual == FB_VISUAL_MONO10)
61 depth = 1;
62 else {
63 if (var->green.length == var->blue.length &&
64 var->green.length == var->red.length &&
65 var->green.offset == var->blue.offset &&
66 var->green.offset == var->red.offset)
67 depth = var->green.length;
68 else
69 depth = var->green.length + var->red.length +
70 var->blue.length;
71 }
72
73 return depth;
74 }
75 EXPORT_SYMBOL(fb_get_color_depth);
76
77 /*
78 * Data padding functions.
79 */
80 void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
81 {
82 __fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height);
83 }
84 EXPORT_SYMBOL(fb_pad_aligned_buffer);
85
86 void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height,
87 u32 shift_high, u32 shift_low, u32 mod)
88 {
89 u8 mask = (u8) (0xfff << shift_high), tmp;
90 int i, j;
91
92 for (i = height; i--; ) {
93 for (j = 0; j < idx; j++) {
94 tmp = dst[j];
95 tmp &= mask;
96 tmp |= *src >> shift_low;
97 dst[j] = tmp;
98 tmp = *src << shift_high;
99 dst[j+1] = tmp;
100 src++;
101 }
102 tmp = dst[idx];
103 tmp &= mask;
104 tmp |= *src >> shift_low;
105 dst[idx] = tmp;
106 if (shift_high < mod) {
107 tmp = *src << shift_high;
108 dst[idx+1] = tmp;
109 }
110 src++;
111 dst += d_pitch;
112 }
113 }
114 EXPORT_SYMBOL(fb_pad_unaligned_buffer);
115
116 /*
117 * we need to lock this section since fb_cursor
118 * may use fb_imageblit()
119 */
120 char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size)
121 {
122 u32 align = buf->buf_align - 1, offset;
123 char *addr = buf->addr;
124
125 /* If IO mapped, we need to sync before access, no sharing of
126 * the pixmap is done
127 */
128 if (buf->flags & FB_PIXMAP_IO) {
129 if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
130 info->fbops->fb_sync(info);
131 return addr;
132 }
133
134 /* See if we fit in the remaining pixmap space */
135 offset = buf->offset + align;
136 offset &= ~align;
137 if (offset + size > buf->size) {
138 /* We do not fit. In order to be able to re-use the buffer,
139 * we must ensure no asynchronous DMA'ing or whatever operation
140 * is in progress, we sync for that.
141 */
142 if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
143 info->fbops->fb_sync(info);
144 offset = 0;
145 }
146 buf->offset = offset + size;
147 addr += offset;
148
149 return addr;
150 }
151
152 #ifdef CONFIG_LOGO
153
154 static inline unsigned safe_shift(unsigned d, int n)
155 {
156 return n < 0 ? d >> -n : d << n;
157 }
158
159 static void fb_set_logocmap(struct fb_info *info,
160 const struct linux_logo *logo)
161 {
162 struct fb_cmap palette_cmap;
163 u16 palette_green[16];
164 u16 palette_blue[16];
165 u16 palette_red[16];
166 int i, j, n;
167 const unsigned char *clut = logo->clut;
168
169 palette_cmap.start = 0;
170 palette_cmap.len = 16;
171 palette_cmap.red = palette_red;
172 palette_cmap.green = palette_green;
173 palette_cmap.blue = palette_blue;
174 palette_cmap.transp = NULL;
175
176 for (i = 0; i < logo->clutsize; i += n) {
177 n = logo->clutsize - i;
178 /* palette_cmap provides space for only 16 colors at once */
179 if (n > 16)
180 n = 16;
181 palette_cmap.start = 32 + i;
182 palette_cmap.len = n;
183 for (j = 0; j < n; ++j) {
184 palette_cmap.red[j] = clut[0] << 8 | clut[0];
185 palette_cmap.green[j] = clut[1] << 8 | clut[1];
186 palette_cmap.blue[j] = clut[2] << 8 | clut[2];
187 clut += 3;
188 }
189 fb_set_cmap(&palette_cmap, info);
190 }
191 }
192
193 static void fb_set_logo_truepalette(struct fb_info *info,
194 const struct linux_logo *logo,
195 u32 *palette)
196 {
197 static const unsigned char mask[] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
198 unsigned char redmask, greenmask, bluemask;
199 int redshift, greenshift, blueshift;
200 int i;
201 const unsigned char *clut = logo->clut;
202
203 /*
204 * We have to create a temporary palette since console palette is only
205 * 16 colors long.
206 */
207 /* Bug: Doesn't obey msb_right ... (who needs that?) */
208 redmask = mask[info->var.red.length < 8 ? info->var.red.length : 8];
209 greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
210 bluemask = mask[info->var.blue.length < 8 ? info->var.blue.length : 8];
211 redshift = info->var.red.offset - (8 - info->var.red.length);
212 greenshift = info->var.green.offset - (8 - info->var.green.length);
213 blueshift = info->var.blue.offset - (8 - info->var.blue.length);
214
215 for ( i = 0; i < logo->clutsize; i++) {
216 palette[i+32] = (safe_shift((clut[0] & redmask), redshift) |
217 safe_shift((clut[1] & greenmask), greenshift) |
218 safe_shift((clut[2] & bluemask), blueshift));
219 clut += 3;
220 }
221 }
222
223 static void fb_set_logo_directpalette(struct fb_info *info,
224 const struct linux_logo *logo,
225 u32 *palette)
226 {
227 int redshift, greenshift, blueshift;
228 int i;
229
230 redshift = info->var.red.offset;
231 greenshift = info->var.green.offset;
232 blueshift = info->var.blue.offset;
233
234 for (i = 32; i < logo->clutsize; i++)
235 palette[i] = i << redshift | i << greenshift | i << blueshift;
236 }
237
238 static void fb_set_logo(struct fb_info *info,
239 const struct linux_logo *logo, u8 *dst,
240 int depth)
241 {
242 int i, j, k;
243 const u8 *src = logo->data;
244 u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
245 u8 fg = 1, d;
246
247 switch (fb_get_color_depth(&info->var, &info->fix)) {
248 case 1:
249 fg = 1;
250 break;
251 case 2:
252 fg = 3;
253 break;
254 default:
255 fg = 7;
256 break;
257 }
258
259 if (info->fix.visual == FB_VISUAL_MONO01 ||
260 info->fix.visual == FB_VISUAL_MONO10)
261 fg = ~((u8) (0xfff << info->var.green.length));
262
263 switch (depth) {
264 case 4:
265 for (i = 0; i < logo->height; i++)
266 for (j = 0; j < logo->width; src++) {
267 *dst++ = *src >> 4;
268 j++;
269 if (j < logo->width) {
270 *dst++ = *src & 0x0f;
271 j++;
272 }
273 }
274 break;
275 case 1:
276 for (i = 0; i < logo->height; i++) {
277 for (j = 0; j < logo->width; src++) {
278 d = *src ^ xor;
279 for (k = 7; k >= 0; k--) {
280 *dst++ = ((d >> k) & 1) ? fg : 0;
281 j++;
282 }
283 }
284 }
285 break;
286 }
287 }
相关阅读 更多 +
排行榜 更多 +