OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [video/] [efifb.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Framebuffer driver for EFI/UEFI based system
3
 *
4
 * (c) 2006 Edgar Hucek <gimli@dark-green.com>
5
 * Original efi driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de>
6
 *
7
 */
8
 
9
#include <linux/module.h>
10
#include <linux/kernel.h>
11
#include <linux/errno.h>
12
#include <linux/fb.h>
13
#include <linux/platform_device.h>
14
#include <linux/screen_info.h>
15
 
16
#include <video/vga.h>
17
 
18
static struct fb_var_screeninfo efifb_defined __initdata = {
19
        .activate               = FB_ACTIVATE_NOW,
20
        .height                 = -1,
21
        .width                  = -1,
22
        .right_margin           = 32,
23
        .upper_margin           = 16,
24
        .lower_margin           = 4,
25
        .vsync_len              = 4,
26
        .vmode                  = FB_VMODE_NONINTERLACED,
27
};
28
 
29
static struct fb_fix_screeninfo efifb_fix __initdata = {
30
        .id                     = "EFI VGA",
31
        .type                   = FB_TYPE_PACKED_PIXELS,
32
        .accel                  = FB_ACCEL_NONE,
33
        .visual                 = FB_VISUAL_TRUECOLOR,
34
};
35
 
36
static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
37
                           unsigned blue, unsigned transp,
38
                           struct fb_info *info)
39
{
40
        /*
41
         *  Set a single color register. The values supplied are
42
         *  already rounded down to the hardware's capabilities
43
         *  (according to the entries in the `var' structure). Return
44
         *  != 0 for invalid regno.
45
         */
46
 
47
        if (regno >= info->cmap.len)
48
                return 1;
49
 
50
        if (regno < 16) {
51
                red   >>= 8;
52
                green >>= 8;
53
                blue  >>= 8;
54
                ((u32 *)(info->pseudo_palette))[regno] =
55
                        (red   << info->var.red.offset)   |
56
                        (green << info->var.green.offset) |
57
                        (blue  << info->var.blue.offset);
58
        }
59
        return 0;
60
}
61
 
62
static struct fb_ops efifb_ops = {
63
        .owner          = THIS_MODULE,
64
        .fb_setcolreg   = efifb_setcolreg,
65
        .fb_fillrect    = cfb_fillrect,
66
        .fb_copyarea    = cfb_copyarea,
67
        .fb_imageblit   = cfb_imageblit,
68
};
69
 
70
static int __init efifb_probe(struct platform_device *dev)
71
{
72
        struct fb_info *info;
73
        int err;
74
        unsigned int size_vmode;
75
        unsigned int size_remap;
76
        unsigned int size_total;
77
 
78
        efifb_fix.smem_start = screen_info.lfb_base;
79
        efifb_defined.bits_per_pixel = screen_info.lfb_depth;
80
        efifb_defined.xres = screen_info.lfb_width;
81
        efifb_defined.yres = screen_info.lfb_height;
82
        efifb_fix.line_length = screen_info.lfb_linelength;
83
 
84
        /*   size_vmode -- that is the amount of memory needed for the
85
         *                 used video mode, i.e. the minimum amount of
86
         *                 memory we need. */
87
        size_vmode = efifb_defined.yres * efifb_fix.line_length;
88
 
89
        /*   size_total -- all video memory we have. Used for
90
         *                 entries, ressource allocation and bounds
91
         *                 checking. */
92
        size_total = screen_info.lfb_size;
93
        if (size_total < size_vmode)
94
                size_total = size_vmode;
95
 
96
        /*   size_remap -- the amount of video memory we are going to
97
         *                 use for efifb.  With modern cards it is no
98
         *                 option to simply use size_total as that
99
         *                 wastes plenty of kernel address space. */
100
        size_remap  = size_vmode * 2;
101
        if (size_remap < size_vmode)
102
                size_remap = size_vmode;
103
        if (size_remap > size_total)
104
                size_remap = size_total;
105
        efifb_fix.smem_len = size_remap;
106
 
107
        if (!request_mem_region(efifb_fix.smem_start, size_total, "efifb"))
108
                /* We cannot make this fatal. Sometimes this comes from magic
109
                   spaces our resource handlers simply don't know about */
110
                printk(KERN_WARNING
111
                       "efifb: cannot reserve video memory at 0x%lx\n",
112
                        efifb_fix.smem_start);
113
 
114
        info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
115
        if (!info) {
116
                err = -ENOMEM;
117
                goto err_release_mem;
118
        }
119
        info->pseudo_palette = info->par;
120
        info->par = NULL;
121
 
122
        info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len);
123
        if (!info->screen_base) {
124
                printk(KERN_ERR "efifb: abort, cannot ioremap video memory "
125
                                "0x%x @ 0x%lx\n",
126
                        efifb_fix.smem_len, efifb_fix.smem_start);
127
                err = -EIO;
128
                goto err_unmap;
129
        }
130
 
131
        printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, "
132
               "using %dk, total %dk\n",
133
               efifb_fix.smem_start, info->screen_base,
134
               size_remap/1024, size_total/1024);
135
        printk(KERN_INFO "efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
136
               efifb_defined.xres, efifb_defined.yres,
137
               efifb_defined.bits_per_pixel, efifb_fix.line_length,
138
               screen_info.pages);
139
 
140
        efifb_defined.xres_virtual = efifb_defined.xres;
141
        efifb_defined.yres_virtual = efifb_fix.smem_len /
142
                                        efifb_fix.line_length;
143
        printk(KERN_INFO "efifb: scrolling: redraw\n");
144
        efifb_defined.yres_virtual = efifb_defined.yres;
145
 
146
        /* some dummy values for timing to make fbset happy */
147
        efifb_defined.pixclock     = 10000000 / efifb_defined.xres *
148
                                        1000 / efifb_defined.yres;
149
        efifb_defined.left_margin  = (efifb_defined.xres / 8) & 0xf8;
150
        efifb_defined.hsync_len    = (efifb_defined.xres / 8) & 0xf8;
151
 
152
        efifb_defined.red.offset    = screen_info.red_pos;
153
        efifb_defined.red.length    = screen_info.red_size;
154
        efifb_defined.green.offset  = screen_info.green_pos;
155
        efifb_defined.green.length  = screen_info.green_size;
156
        efifb_defined.blue.offset   = screen_info.blue_pos;
157
        efifb_defined.blue.length   = screen_info.blue_size;
158
        efifb_defined.transp.offset = screen_info.rsvd_pos;
159
        efifb_defined.transp.length = screen_info.rsvd_size;
160
 
161
        printk(KERN_INFO "efifb: %s: "
162
               "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
163
               "Truecolor",
164
               screen_info.rsvd_size,
165
               screen_info.red_size,
166
               screen_info.green_size,
167
               screen_info.blue_size,
168
               screen_info.rsvd_pos,
169
               screen_info.red_pos,
170
               screen_info.green_pos,
171
               screen_info.blue_pos);
172
 
173
        efifb_fix.ypanstep  = 0;
174
        efifb_fix.ywrapstep = 0;
175
 
176
        info->fbops = &efifb_ops;
177
        info->var = efifb_defined;
178
        info->fix = efifb_fix;
179
        info->flags = FBINFO_FLAG_DEFAULT;
180
 
181
        if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
182
                err = -ENOMEM;
183
                goto err_unmap;
184
        }
185
        if (register_framebuffer(info) < 0) {
186
                err = -EINVAL;
187
                goto err_fb_dealoc;
188
        }
189
        printk(KERN_INFO "fb%d: %s frame buffer device\n",
190
               info->node, info->fix.id);
191
        return 0;
192
 
193
err_fb_dealoc:
194
        fb_dealloc_cmap(&info->cmap);
195
err_unmap:
196
        iounmap(info->screen_base);
197
        framebuffer_release(info);
198
err_release_mem:
199
        release_mem_region(efifb_fix.smem_start, size_total);
200
        return err;
201
}
202
 
203
static struct platform_driver efifb_driver = {
204
        .probe  = efifb_probe,
205
        .driver = {
206
                .name   = "efifb",
207
        },
208
};
209
 
210
static struct platform_device efifb_device = {
211
        .name   = "efifb",
212
};
213
 
214
static int __init efifb_init(void)
215
{
216
        int ret;
217
 
218
        if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
219
                return -ENODEV;
220
 
221
        ret = platform_driver_register(&efifb_driver);
222
 
223
        if (!ret) {
224
                ret = platform_device_register(&efifb_device);
225
                if (ret)
226
                        platform_driver_unregister(&efifb_driver);
227
        }
228
        return ret;
229
}
230
module_init(efifb_init);
231
 
232
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.