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

Subversion Repositories test_project

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* leo.c: LEO frame buffer driver
2
 *
3
 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
4
 * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
5
 * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
6
 *
7
 * Driver layout based loosely on tgafb.c, see that file for credits.
8
 */
9
 
10
#include <linux/module.h>
11
#include <linux/kernel.h>
12
#include <linux/errno.h>
13
#include <linux/string.h>
14
#include <linux/slab.h>
15
#include <linux/delay.h>
16
#include <linux/init.h>
17
#include <linux/fb.h>
18
#include <linux/mm.h>
19
 
20
#include <asm/io.h>
21
#include <asm/prom.h>
22
#include <asm/of_device.h>
23
#include <asm/fbio.h>
24
 
25
#include "sbuslib.h"
26
 
27
/*
28
 * Local functions.
29
 */
30
 
31
static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned,
32
                         unsigned, struct fb_info *);
33
static int leo_blank(int, struct fb_info *);
34
 
35
static int leo_mmap(struct fb_info *, struct vm_area_struct *);
36
static int leo_ioctl(struct fb_info *, unsigned int, unsigned long);
37
static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *);
38
 
39
/*
40
 *  Frame buffer operations
41
 */
42
 
43
static struct fb_ops leo_ops = {
44
        .owner                  = THIS_MODULE,
45
        .fb_setcolreg           = leo_setcolreg,
46
        .fb_blank               = leo_blank,
47
        .fb_pan_display         = leo_pan_display,
48
        .fb_fillrect            = cfb_fillrect,
49
        .fb_copyarea            = cfb_copyarea,
50
        .fb_imageblit           = cfb_imageblit,
51
        .fb_mmap                = leo_mmap,
52
        .fb_ioctl               = leo_ioctl,
53
#ifdef CONFIG_COMPAT
54
        .fb_compat_ioctl        = sbusfb_compat_ioctl,
55
#endif
56
};
57
 
58
#define LEO_OFF_LC_SS0_KRN      0x00200000UL
59
#define LEO_OFF_LC_SS0_USR      0x00201000UL
60
#define LEO_OFF_LC_SS1_KRN      0x01200000UL
61
#define LEO_OFF_LC_SS1_USR      0x01201000UL
62
#define LEO_OFF_LD_SS0          0x00400000UL
63
#define LEO_OFF_LD_SS1          0x01400000UL
64
#define LEO_OFF_LD_GBL          0x00401000UL
65
#define LEO_OFF_LX_KRN          0x00600000UL
66
#define LEO_OFF_LX_CURSOR       0x00601000UL
67
#define LEO_OFF_SS0             0x00800000UL
68
#define LEO_OFF_SS1             0x01800000UL
69
#define LEO_OFF_UNK             0x00602000UL
70
#define LEO_OFF_UNK2            0x00000000UL
71
 
72
#define LEO_CUR_ENABLE          0x00000080
73
#define LEO_CUR_UPDATE          0x00000030
74
#define LEO_CUR_PROGRESS        0x00000006
75
#define LEO_CUR_UPDATECMAP      0x00000003
76
 
77
#define LEO_CUR_TYPE_MASK       0x00000000
78
#define LEO_CUR_TYPE_IMAGE      0x00000020
79
#define LEO_CUR_TYPE_CMAP       0x00000050
80
 
81
struct leo_cursor {
82
        u8              xxx0[16];
83
        u32     cur_type;
84
        u32     cur_misc;
85
        u32     cur_cursxy;
86
        u32     cur_data;
87
};
88
 
89
#define LEO_KRN_TYPE_CLUT0      0x00001000
90
#define LEO_KRN_TYPE_CLUT1      0x00001001
91
#define LEO_KRN_TYPE_CLUT2      0x00001002
92
#define LEO_KRN_TYPE_WID        0x00001003
93
#define LEO_KRN_TYPE_UNK        0x00001006
94
#define LEO_KRN_TYPE_VIDEO      0x00002003
95
#define LEO_KRN_TYPE_CLUTDATA   0x00004000
96
#define LEO_KRN_CSR_ENABLE      0x00000008
97
#define LEO_KRN_CSR_PROGRESS    0x00000004
98
#define LEO_KRN_CSR_UNK         0x00000002
99
#define LEO_KRN_CSR_UNK2        0x00000001
100
 
101
struct leo_lx_krn {
102
        u32     krn_type;
103
        u32     krn_csr;
104
        u32     krn_value;
105
};
106
 
107
struct leo_lc_ss0_krn {
108
        u32     misc;
109
        u8              xxx0[0x800-4];
110
        u32     rev;
111
};
112
 
113
struct leo_lc_ss0_usr {
114
        u32     csr;
115
        u32     addrspace;
116
        u32     fontmsk;
117
        u32     fontt;
118
        u32     extent;
119
        u32     src;
120
        u32             dst;
121
        u32     copy;
122
        u32     fill;
123
};
124
 
125
struct leo_lc_ss1_krn {
126
        u8      unknown;
127
};
128
 
129
struct leo_lc_ss1_usr {
130
        u8      unknown;
131
};
132
 
133
struct leo_ld {
134
        u8              xxx0[0xe00];
135
        u32     csr;
136
        u32     wid;
137
        u32     wmask;
138
        u32     widclip;
139
        u32     vclipmin;
140
        u32     vclipmax;
141
        u32     pickmin;        /* SS1 only */
142
        u32     pickmax;        /* SS1 only */
143
        u32     fg;
144
        u32     bg;
145
        u32     src;            /* Copy/Scroll (SS0 only) */
146
        u32     dst;            /* Copy/Scroll/Fill (SS0 only) */
147
        u32     extent;         /* Copy/Scroll/Fill size (SS0 only) */
148
        u32             xxx1[3];
149
        u32     setsem;         /* SS1 only */
150
        u32     clrsem;         /* SS1 only */
151
        u32     clrpick;        /* SS1 only */
152
        u32     clrdat;         /* SS1 only */
153
        u32     alpha;          /* SS1 only */
154
        u8              xxx2[0x2c];
155
        u32     winbg;
156
        u32     planemask;
157
        u32     rop;
158
        u32     z;
159
        u32     dczf;           /* SS1 only */
160
        u32     dczb;           /* SS1 only */
161
        u32     dcs;            /* SS1 only */
162
        u32     dczs;           /* SS1 only */
163
        u32     pickfb;         /* SS1 only */
164
        u32     pickbb;         /* SS1 only */
165
        u32     dcfc;           /* SS1 only */
166
        u32     forcecol;       /* SS1 only */
167
        u32     door[8];        /* SS1 only */
168
        u32     pick[5];        /* SS1 only */
169
};
170
 
171
#define LEO_SS1_MISC_ENABLE     0x00000001
172
#define LEO_SS1_MISC_STEREO     0x00000002
173
struct leo_ld_ss1 {
174
        u8      xxx0[0xef4];
175
        u32     ss1_misc;
176
};
177
 
178
struct leo_ld_gbl {
179
        u8      unknown;
180
};
181
 
182
struct leo_par {
183
        spinlock_t              lock;
184
        struct leo_lx_krn       __iomem *lx_krn;
185
        struct leo_lc_ss0_usr   __iomem *lc_ss0_usr;
186
        struct leo_ld_ss0       __iomem *ld_ss0;
187
        struct leo_ld_ss1       __iomem *ld_ss1;
188
        struct leo_cursor       __iomem *cursor;
189
        u32                     extent;
190
        u32                     clut_data[256];
191
 
192
        u32                     flags;
193
#define LEO_FLAG_BLANKED        0x00000001
194
 
195
        unsigned long           physbase;
196
        unsigned long           which_io;
197
        unsigned long           fbsize;
198
};
199
 
200
static void leo_wait(struct leo_lx_krn __iomem *lx_krn)
201
{
202
        int i;
203
 
204
        for (i = 0;
205
             (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000;
206
             i++)
207
                udelay (1); /* Busy wait at most 0.3 sec */
208
        return;
209
}
210
 
211
/**
212
 *      leo_setcolreg - Optional function. Sets a color register.
213
 *      @regno: boolean, 0 copy local, 1 get_user() function
214
 *      @red: frame buffer colormap structure
215
 *      @green: The green value which can be up to 16 bits wide
216
 *      @blue:  The blue value which can be up to 16 bits wide.
217
 *      @transp: If supported the alpha value which can be up to 16 bits wide.
218
 *      @info: frame buffer info structure
219
 */
220
static int leo_setcolreg(unsigned regno,
221
                         unsigned red, unsigned green, unsigned blue,
222
                         unsigned transp, struct fb_info *info)
223
{
224
        struct leo_par *par = (struct leo_par *) info->par;
225
        struct leo_lx_krn __iomem *lx_krn = par->lx_krn;
226
        unsigned long flags;
227
        u32 val;
228
        int i;
229
 
230
        if (regno >= 256)
231
                return 1;
232
 
233
        red >>= 8;
234
        green >>= 8;
235
        blue >>= 8;
236
 
237
        par->clut_data[regno] = red | (green << 8) | (blue << 16);
238
 
239
        spin_lock_irqsave(&par->lock, flags);
240
 
241
        leo_wait(lx_krn);
242
 
243
        sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
244
        for (i = 0; i < 256; i++)
245
                sbus_writel(par->clut_data[i], &lx_krn->krn_value);
246
        sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
247
 
248
        val = sbus_readl(&lx_krn->krn_csr);
249
        val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
250
        sbus_writel(val, &lx_krn->krn_csr);
251
 
252
        spin_unlock_irqrestore(&par->lock, flags);
253
 
254
        return 0;
255
}
256
 
257
/**
258
 *      leo_blank - Optional function.  Blanks the display.
259
 *      @blank_mode: the blank mode we want.
260
 *      @info: frame buffer structure that represents a single frame buffer
261
 */
262
static int leo_blank(int blank, struct fb_info *info)
263
{
264
        struct leo_par *par = (struct leo_par *) info->par;
265
        struct leo_lx_krn __iomem *lx_krn = par->lx_krn;
266
        unsigned long flags;
267
        u32 val;
268
 
269
        spin_lock_irqsave(&par->lock, flags);
270
 
271
        switch (blank) {
272
        case FB_BLANK_UNBLANK: /* Unblanking */
273
                val = sbus_readl(&lx_krn->krn_csr);
274
                val |= LEO_KRN_CSR_ENABLE;
275
                sbus_writel(val, &lx_krn->krn_csr);
276
                par->flags &= ~LEO_FLAG_BLANKED;
277
                break;
278
 
279
        case FB_BLANK_NORMAL: /* Normal blanking */
280
        case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
281
        case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
282
        case FB_BLANK_POWERDOWN: /* Poweroff */
283
                val = sbus_readl(&lx_krn->krn_csr);
284
                val &= ~LEO_KRN_CSR_ENABLE;
285
                sbus_writel(val, &lx_krn->krn_csr);
286
                par->flags |= LEO_FLAG_BLANKED;
287
                break;
288
        }
289
 
290
        spin_unlock_irqrestore(&par->lock, flags);
291
 
292
        return 0;
293
}
294
 
295
static struct sbus_mmap_map leo_mmap_map[] = {
296
        {
297
                .voff   = LEO_SS0_MAP,
298
                .poff   = LEO_OFF_SS0,
299
                .size   = 0x800000
300
        },
301
        {
302
                .voff   = LEO_LC_SS0_USR_MAP,
303
                .poff   = LEO_OFF_LC_SS0_USR,
304
                .size   = 0x1000
305
        },
306
        {
307
                .voff   = LEO_LD_SS0_MAP,
308
                .poff   = LEO_OFF_LD_SS0,
309
                .size   = 0x1000
310
        },
311
        {
312
                .voff   = LEO_LX_CURSOR_MAP,
313
                .poff   = LEO_OFF_LX_CURSOR,
314
                .size   = 0x1000
315
        },
316
        {
317
                .voff   = LEO_SS1_MAP,
318
                .poff   = LEO_OFF_SS1,
319
                .size   = 0x800000
320
        },
321
        {
322
                .voff   = LEO_LC_SS1_USR_MAP,
323
                .poff   = LEO_OFF_LC_SS1_USR,
324
                .size   = 0x1000
325
        },
326
        {
327
                .voff   = LEO_LD_SS1_MAP,
328
                .poff   = LEO_OFF_LD_SS1,
329
                .size   = 0x1000
330
        },
331
        {
332
                .voff   = LEO_UNK_MAP,
333
                .poff   = LEO_OFF_UNK,
334
                .size   = 0x1000
335
        },
336
        {
337
                .voff   = LEO_LX_KRN_MAP,
338
                .poff   = LEO_OFF_LX_KRN,
339
                .size   = 0x1000
340
        },
341
        {
342
                .voff   = LEO_LC_SS0_KRN_MAP,
343
                .poff   = LEO_OFF_LC_SS0_KRN,
344
                .size   = 0x1000
345
        },
346
        {
347
                .voff   = LEO_LC_SS1_KRN_MAP,
348
                .poff   = LEO_OFF_LC_SS1_KRN,
349
                .size   = 0x1000
350
        },
351
        {
352
                .voff   = LEO_LD_GBL_MAP,
353
                .poff   = LEO_OFF_LD_GBL,
354
                .size   = 0x1000
355
        },
356
        {
357
                .voff   = LEO_UNK2_MAP,
358
                .poff   = LEO_OFF_UNK2,
359
                .size   = 0x100000
360
        },
361
        { .size = 0 }
362
};
363
 
364
static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma)
365
{
366
        struct leo_par *par = (struct leo_par *)info->par;
367
 
368
        return sbusfb_mmap_helper(leo_mmap_map,
369
                                  par->physbase, par->fbsize,
370
                                  par->which_io, vma);
371
}
372
 
373
static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
374
{
375
        struct leo_par *par = (struct leo_par *) info->par;
376
 
377
        return sbusfb_ioctl_helper(cmd, arg, info,
378
                                   FBTYPE_SUNLEO, 32, par->fbsize);
379
}
380
 
381
/*
382
 *  Initialisation
383
 */
384
 
385
static void
386
leo_init_fix(struct fb_info *info, struct device_node *dp)
387
{
388
        strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
389
 
390
        info->fix.type = FB_TYPE_PACKED_PIXELS;
391
        info->fix.visual = FB_VISUAL_TRUECOLOR;
392
 
393
        info->fix.line_length = 8192;
394
 
395
        info->fix.accel = FB_ACCEL_SUN_LEO;
396
}
397
 
398
static void leo_wid_put(struct fb_info *info, struct fb_wid_list *wl)
399
{
400
        struct leo_par *par = (struct leo_par *) info->par;
401
        struct leo_lx_krn __iomem *lx_krn = par->lx_krn;
402
        struct fb_wid_item *wi;
403
        unsigned long flags;
404
        u32 val;
405
        int i, j;
406
 
407
        spin_lock_irqsave(&par->lock, flags);
408
 
409
        leo_wait(lx_krn);
410
 
411
        for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
412
                switch(wi->wi_type) {
413
                case FB_WID_DBL_8:
414
                        j = (wi->wi_index & 0xf) + 0x40;
415
                        break;
416
 
417
                case FB_WID_DBL_24:
418
                        j = wi->wi_index & 0x3f;
419
                        break;
420
 
421
                default:
422
                        continue;
423
                };
424
                sbus_writel(0x5800 + j, &lx_krn->krn_type);
425
                sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
426
        }
427
        sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
428
 
429
        val = sbus_readl(&lx_krn->krn_csr);
430
        val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
431
        sbus_writel(val, &lx_krn->krn_csr);
432
 
433
        spin_unlock_irqrestore(&par->lock, flags);
434
}
435
 
436
static void leo_init_wids(struct fb_info *info)
437
{
438
        struct fb_wid_item wi;
439
        struct fb_wid_list wl;
440
 
441
        wl.wl_count = 1;
442
        wl.wl_list = &wi;
443
        wi.wi_type = FB_WID_DBL_8;
444
        wi.wi_index = 0;
445
        wi.wi_values [0] = 0x2c0;
446
        leo_wid_put(info, &wl);
447
        wi.wi_index = 1;
448
        wi.wi_values [0] = 0x30;
449
        leo_wid_put(info, &wl);
450
        wi.wi_index = 2;
451
        wi.wi_values [0] = 0x20;
452
        leo_wid_put(info, &wl);
453
        wi.wi_type = FB_WID_DBL_24;
454
        wi.wi_index = 1;
455
        wi.wi_values [0] = 0x30;
456
        leo_wid_put(info, &wl);
457
 
458
}
459
 
460
static void leo_switch_from_graph(struct fb_info *info)
461
{
462
        struct leo_par *par = (struct leo_par *) info->par;
463
        struct leo_ld __iomem *ss = (struct leo_ld __iomem *) par->ld_ss0;
464
        unsigned long flags;
465
        u32 val;
466
 
467
        spin_lock_irqsave(&par->lock, flags);
468
 
469
        par->extent = ((info->var.xres - 1) |
470
                       ((info->var.yres - 1) << 16));
471
 
472
        sbus_writel(0xffffffff, &ss->wid);
473
        sbus_writel(0xffff, &ss->wmask);
474
        sbus_writel(0, &ss->vclipmin);
475
        sbus_writel(par->extent, &ss->vclipmax);
476
        sbus_writel(0, &ss->fg);
477
        sbus_writel(0xff000000, &ss->planemask);
478
        sbus_writel(0x310850, &ss->rop);
479
        sbus_writel(0, &ss->widclip);
480
        sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11),
481
                    &par->lc_ss0_usr->extent);
482
        sbus_writel(4, &par->lc_ss0_usr->addrspace);
483
        sbus_writel(0x80000000, &par->lc_ss0_usr->fill);
484
        sbus_writel(0, &par->lc_ss0_usr->fontt);
485
        do {
486
                val = sbus_readl(&par->lc_ss0_usr->csr);
487
        } while (val & 0x20000000);
488
 
489
        spin_unlock_irqrestore(&par->lock, flags);
490
}
491
 
492
static int leo_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
493
{
494
        /* We just use this to catch switches out of
495
         * graphics mode.
496
         */
497
        leo_switch_from_graph(info);
498
 
499
        if (var->xoffset || var->yoffset || var->vmode)
500
                return -EINVAL;
501
        return 0;
502
}
503
 
504
static void leo_init_hw(struct fb_info *info)
505
{
506
        struct leo_par *par = (struct leo_par *) info->par;
507
        u32 val;
508
 
509
        val = sbus_readl(&par->ld_ss1->ss1_misc);
510
        val |= LEO_SS1_MISC_ENABLE;
511
        sbus_writel(val, &par->ld_ss1->ss1_misc);
512
 
513
        leo_switch_from_graph(info);
514
}
515
 
516
static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
517
{
518
        var->red.offset = 0;
519
        var->red.length = 8;
520
        var->green.offset = 8;
521
        var->green.length = 8;
522
        var->blue.offset = 16;
523
        var->blue.length = 8;
524
        var->transp.offset = 0;
525
        var->transp.length = 0;
526
}
527
 
528
static void leo_unmap_regs(struct of_device *op, struct fb_info *info,
529
                           struct leo_par *par)
530
{
531
        if (par->lc_ss0_usr)
532
                of_iounmap(&op->resource[0], par->lc_ss0_usr, 0x1000);
533
        if (par->ld_ss0)
534
                of_iounmap(&op->resource[0], par->ld_ss0, 0x1000);
535
        if (par->ld_ss1)
536
                of_iounmap(&op->resource[0], par->ld_ss1, 0x1000);
537
        if (par->lx_krn)
538
                of_iounmap(&op->resource[0], par->lx_krn, 0x1000);
539
        if (par->cursor)
540
                of_iounmap(&op->resource[0],
541
                           par->cursor, sizeof(struct leo_cursor));
542
        if (info->screen_base)
543
                of_iounmap(&op->resource[0], info->screen_base, 0x800000);
544
}
545
 
546
static int __devinit leo_probe(struct of_device *op, const struct of_device_id *match)
547
{
548
        struct device_node *dp = op->node;
549
        struct fb_info *info;
550
        struct leo_par *par;
551
        int linebytes, err;
552
 
553
        info = framebuffer_alloc(sizeof(struct leo_par), &op->dev);
554
 
555
        err = -ENOMEM;
556
        if (!info)
557
                goto out_err;
558
        par = info->par;
559
 
560
        spin_lock_init(&par->lock);
561
 
562
        par->physbase = op->resource[0].start;
563
        par->which_io = op->resource[0].flags & IORESOURCE_BITS;
564
 
565
        sbusfb_fill_var(&info->var, dp->node, 32);
566
        leo_fixup_var_rgb(&info->var);
567
 
568
        linebytes = of_getintprop_default(dp, "linebytes",
569
                                          info->var.xres);
570
        par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
571
 
572
        par->lc_ss0_usr =
573
                of_ioremap(&op->resource[0], LEO_OFF_LC_SS0_USR,
574
                           0x1000, "leolc ss0usr");
575
        par->ld_ss0 =
576
                of_ioremap(&op->resource[0], LEO_OFF_LD_SS0,
577
                           0x1000, "leold ss0");
578
        par->ld_ss1 =
579
                of_ioremap(&op->resource[0], LEO_OFF_LD_SS1,
580
                           0x1000, "leold ss1");
581
        par->lx_krn =
582
                of_ioremap(&op->resource[0], LEO_OFF_LX_KRN,
583
                           0x1000, "leolx krn");
584
        par->cursor =
585
                of_ioremap(&op->resource[0], LEO_OFF_LX_CURSOR,
586
                           sizeof(struct leo_cursor), "leolx cursor");
587
        info->screen_base =
588
                of_ioremap(&op->resource[0], LEO_OFF_SS0,
589
                           0x800000, "leo ram");
590
        if (!par->lc_ss0_usr ||
591
            !par->ld_ss0 ||
592
            !par->ld_ss1 ||
593
            !par->lx_krn ||
594
            !par->cursor ||
595
            !info->screen_base)
596
                goto out_unmap_regs;
597
 
598
        info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
599
        info->fbops = &leo_ops;
600
 
601
        leo_init_wids(info);
602
        leo_init_hw(info);
603
 
604
        leo_blank(0, info);
605
 
606
        if (fb_alloc_cmap(&info->cmap, 256, 0))
607
                goto out_unmap_regs;
608
 
609
        leo_init_fix(info, dp);
610
 
611
        err = register_framebuffer(info);
612
        if (err < 0)
613
                goto out_dealloc_cmap;
614
 
615
        dev_set_drvdata(&op->dev, info);
616
 
617
        printk("%s: leo at %lx:%lx\n",
618
               dp->full_name,
619
               par->which_io, par->physbase);
620
 
621
        return 0;
622
 
623
out_dealloc_cmap:
624
        fb_dealloc_cmap(&info->cmap);
625
 
626
out_unmap_regs:
627
        leo_unmap_regs(op, info, par);
628
        framebuffer_release(info);
629
 
630
out_err:
631
        return err;
632
}
633
 
634
static int __devexit leo_remove(struct of_device *op)
635
{
636
        struct fb_info *info = dev_get_drvdata(&op->dev);
637
        struct leo_par *par = info->par;
638
 
639
        unregister_framebuffer(info);
640
        fb_dealloc_cmap(&info->cmap);
641
 
642
        leo_unmap_regs(op, info, par);
643
 
644
        framebuffer_release(info);
645
 
646
        dev_set_drvdata(&op->dev, NULL);
647
 
648
        return 0;
649
}
650
 
651
static struct of_device_id leo_match[] = {
652
        {
653
                .name = "leo",
654
        },
655
        {},
656
};
657
MODULE_DEVICE_TABLE(of, leo_match);
658
 
659
static struct of_platform_driver leo_driver = {
660
        .name           = "leo",
661
        .match_table    = leo_match,
662
        .probe          = leo_probe,
663
        .remove         = __devexit_p(leo_remove),
664
};
665
 
666
static int __init leo_init(void)
667
{
668
        if (fb_get_options("leofb", NULL))
669
                return -ENODEV;
670
 
671
        return of_register_driver(&leo_driver, &of_bus_type);
672
}
673
 
674
static void __exit leo_exit(void)
675
{
676
        of_unregister_driver(&leo_driver);
677
}
678
 
679
module_init(leo_init);
680
module_exit(leo_exit);
681
 
682
MODULE_DESCRIPTION("framebuffer driver for LEO chipsets");
683
MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
684
MODULE_VERSION("2.0");
685
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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