~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/video/leo.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

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