root/drivers/video/fbdev/leo.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. leo_wait
  2. leo_switch_from_graph
  3. leo_pan_display
  4. leo_setcolreg
  5. leo_blank
  6. leo_mmap
  7. leo_ioctl
  8. leo_init_fix
  9. leo_wid_put
  10. leo_init_wids
  11. leo_init_hw
  12. leo_fixup_var_rgb
  13. leo_unmap_regs
  14. leo_probe
  15. leo_remove
  16. leo_init
  17. leo_exit

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

/* [<][>][^][v][top][bottom][index][help] */