LCOV - code coverage report
Current view: top level - drivers/video - fbmem.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 14 753 1.9 %
Date: 2014-02-18 Functions: 6 45 13.3 %
Branches: 8 576 1.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *  linux/drivers/video/fbmem.c
       3                 :            :  *
       4                 :            :  *  Copyright (C) 1994 Martin Schaller
       5                 :            :  *
       6                 :            :  *      2001 - Documented with DocBook
       7                 :            :  *      - Brad Douglas <brad@neruo.com>
       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/kernel.h>
      20                 :            : #include <linux/major.h>
      21                 :            : #include <linux/slab.h>
      22                 :            : #include <linux/mm.h>
      23                 :            : #include <linux/mman.h>
      24                 :            : #include <linux/vt.h>
      25                 :            : #include <linux/init.h>
      26                 :            : #include <linux/linux_logo.h>
      27                 :            : #include <linux/proc_fs.h>
      28                 :            : #include <linux/seq_file.h>
      29                 :            : #include <linux/console.h>
      30                 :            : #include <linux/kmod.h>
      31                 :            : #include <linux/err.h>
      32                 :            : #include <linux/device.h>
      33                 :            : #include <linux/efi.h>
      34                 :            : #include <linux/fb.h>
      35                 :            : 
      36                 :            : #include <asm/fb.h>
      37                 :            : 
      38                 :            : 
      39                 :            :     /*
      40                 :            :      *  Frame buffer device initialization and setup routines
      41                 :            :      */
      42                 :            : 
      43                 :            : #define FBPIXMAPSIZE    (1024 * 8)
      44                 :            : 
      45                 :            : static DEFINE_MUTEX(registration_lock);
      46                 :            : 
      47                 :            : struct fb_info *registered_fb[FB_MAX] __read_mostly;
      48                 :            : EXPORT_SYMBOL(registered_fb);
      49                 :            : 
      50                 :            : int num_registered_fb __read_mostly;
      51                 :            : EXPORT_SYMBOL(num_registered_fb);
      52                 :            : 
      53                 :          0 : static struct fb_info *get_fb_info(unsigned int idx)
      54                 :            : {
      55                 :            :         struct fb_info *fb_info;
      56                 :            : 
      57         [ #  # ]:          0 :         if (idx >= FB_MAX)
      58                 :            :                 return ERR_PTR(-ENODEV);
      59                 :            : 
      60                 :          0 :         mutex_lock(&registration_lock);
      61                 :          0 :         fb_info = registered_fb[idx];
      62         [ #  # ]:          0 :         if (fb_info)
      63                 :          0 :                 atomic_inc(&fb_info->count);
      64                 :          0 :         mutex_unlock(&registration_lock);
      65                 :            : 
      66                 :          0 :         return fb_info;
      67                 :            : }
      68                 :            : 
      69                 :          0 : static void put_fb_info(struct fb_info *fb_info)
      70                 :            : {
      71         [ #  # ]:          0 :         if (!atomic_dec_and_test(&fb_info->count))
      72                 :          0 :                 return;
      73         [ #  # ]:          0 :         if (fb_info->fbops->fb_destroy)
      74                 :          0 :                 fb_info->fbops->fb_destroy(fb_info);
      75                 :            : }
      76                 :            : 
      77                 :          0 : int lock_fb_info(struct fb_info *info)
      78                 :            : {
      79                 :          0 :         mutex_lock(&info->lock);
      80         [ #  # ]:          0 :         if (!info->fbops) {
      81                 :          0 :                 mutex_unlock(&info->lock);
      82                 :          0 :                 return 0;
      83                 :            :         }
      84                 :            :         return 1;
      85                 :            : }
      86                 :            : EXPORT_SYMBOL(lock_fb_info);
      87                 :            : 
      88                 :            : /*
      89                 :            :  * Helpers
      90                 :            :  */
      91                 :            : 
      92                 :          0 : int fb_get_color_depth(struct fb_var_screeninfo *var,
      93                 :            :                        struct fb_fix_screeninfo *fix)
      94                 :            : {
      95                 :            :         int depth = 0;
      96                 :            : 
      97            [ + ]:         56 :         if (fix->visual == FB_VISUAL_MONO01 ||
      98                 :            :             fix->visual == FB_VISUAL_MONO10)
      99                 :            :                 depth = 1;
     100                 :            :         else {
     101 [ -  + ][ #  # ]:        112 :                 if (var->green.length == var->blue.length &&
     102         [ #  # ]:          0 :                     var->green.length == var->red.length &&
     103         [ #  # ]:          0 :                     var->green.offset == var->blue.offset &&
     104                 :          0 :                     var->green.offset == var->red.offset)
     105                 :          0 :                         depth = var->green.length;
     106                 :            :                 else
     107                 :         56 :                         depth = var->green.length + var->red.length +
     108                 :            :                                 var->blue.length;
     109                 :            :         }
     110                 :            : 
     111                 :          0 :         return depth;
     112                 :            : }
     113                 :            : EXPORT_SYMBOL(fb_get_color_depth);
     114                 :            : 
     115                 :            : /*
     116                 :            :  * Data padding functions.
     117                 :            :  */
     118                 :          0 : void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
     119                 :            : {
     120                 :            :         __fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height);
     121                 :          0 : }
     122                 :            : EXPORT_SYMBOL(fb_pad_aligned_buffer);
     123                 :            : 
     124                 :          0 : void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height,
     125                 :            :                                 u32 shift_high, u32 shift_low, u32 mod)
     126                 :            : {
     127                 :          0 :         u8 mask = (u8) (0xfff << shift_high), tmp;
     128                 :            :         int i, j;
     129                 :            : 
     130         [ #  # ]:          0 :         for (i = height; i--; ) {
     131         [ #  # ]:          0 :                 for (j = 0; j < idx; j++) {
     132                 :          0 :                         tmp = dst[j];
     133                 :          0 :                         tmp &= mask;
     134                 :          0 :                         tmp |= *src >> shift_low;
     135                 :          0 :                         dst[j] = tmp;
     136                 :          0 :                         tmp = *src << shift_high;
     137                 :          0 :                         dst[j+1] = tmp;
     138                 :          0 :                         src++;
     139                 :            :                 }
     140                 :          0 :                 tmp = dst[idx];
     141                 :          0 :                 tmp &= mask;
     142                 :          0 :                 tmp |= *src >> shift_low;
     143                 :          0 :                 dst[idx] = tmp;
     144         [ #  # ]:          0 :                 if (shift_high < mod) {
     145                 :          0 :                         tmp = *src << shift_high;
     146                 :          0 :                         dst[idx+1] = tmp;
     147                 :            :                 }
     148                 :          0 :                 src++;
     149                 :          0 :                 dst += d_pitch;
     150                 :            :         }
     151                 :          0 : }
     152                 :            : EXPORT_SYMBOL(fb_pad_unaligned_buffer);
     153                 :            : 
     154                 :            : /*
     155                 :            :  * we need to lock this section since fb_cursor
     156                 :            :  * may use fb_imageblit()
     157                 :            :  */
     158                 :          0 : char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size)
     159                 :            : {
     160                 :          0 :         u32 align = buf->buf_align - 1, offset;
     161                 :          0 :         char *addr = buf->addr;
     162                 :            : 
     163                 :            :         /* If IO mapped, we need to sync before access, no sharing of
     164                 :            :          * the pixmap is done
     165                 :            :          */
     166         [ #  # ]:          0 :         if (buf->flags & FB_PIXMAP_IO) {
     167 [ #  # ][ #  # ]:          0 :                 if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
     168                 :          0 :                         info->fbops->fb_sync(info);
     169                 :          0 :                 return addr;
     170                 :            :         }
     171                 :            : 
     172                 :            :         /* See if we fit in the remaining pixmap space */
     173                 :          0 :         offset = buf->offset + align;
     174                 :          0 :         offset &= ~align;
     175         [ #  # ]:          0 :         if (offset + size > buf->size) {
     176                 :            :                 /* We do not fit. In order to be able to re-use the buffer,
     177                 :            :                  * we must ensure no asynchronous DMA'ing or whatever operation
     178                 :            :                  * is in progress, we sync for that.
     179                 :            :                  */
     180 [ #  # ][ #  # ]:          0 :                 if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
     181                 :          0 :                         info->fbops->fb_sync(info);
     182                 :            :                 offset = 0;
     183                 :            :         }
     184                 :          0 :         buf->offset = offset + size;
     185                 :          0 :         addr += offset;
     186                 :            : 
     187                 :          0 :         return addr;
     188                 :            : }
     189                 :            : EXPORT_SYMBOL(fb_get_buffer_offset);
     190                 :            : 
     191                 :            : #ifdef CONFIG_LOGO
     192                 :            : 
     193                 :            : static inline unsigned safe_shift(unsigned d, int n)
     194                 :            : {
     195 [ #  # ][ #  # ]:          0 :         return n < 0 ? d >> -n : d << n;
                 [ #  # ]
     196                 :            : }
     197                 :            : 
     198                 :          0 : static void fb_set_logocmap(struct fb_info *info,
     199                 :            :                                    const struct linux_logo *logo)
     200                 :            : {
     201                 :            :         struct fb_cmap palette_cmap;
     202                 :            :         u16 palette_green[16];
     203                 :            :         u16 palette_blue[16];
     204                 :            :         u16 palette_red[16];
     205                 :            :         int i, j, n;
     206                 :          0 :         const unsigned char *clut = logo->clut;
     207                 :            : 
     208                 :          0 :         palette_cmap.start = 0;
     209                 :          0 :         palette_cmap.len = 16;
     210                 :          0 :         palette_cmap.red = palette_red;
     211                 :          0 :         palette_cmap.green = palette_green;
     212                 :          0 :         palette_cmap.blue = palette_blue;
     213                 :          0 :         palette_cmap.transp = NULL;
     214                 :            : 
     215         [ #  # ]:          0 :         for (i = 0; i < logo->clutsize; i += n) {
     216                 :          0 :                 n = logo->clutsize - i;
     217                 :            :                 /* palette_cmap provides space for only 16 colors at once */
     218         [ #  # ]:          0 :                 if (n > 16)
     219                 :            :                         n = 16;
     220                 :          0 :                 palette_cmap.start = 32 + i;
     221                 :          0 :                 palette_cmap.len = n;
     222         [ #  # ]:          0 :                 for (j = 0; j < n; ++j) {
     223                 :          0 :                         palette_cmap.red[j] = clut[0] << 8 | clut[0];
     224                 :          0 :                         palette_cmap.green[j] = clut[1] << 8 | clut[1];
     225                 :          0 :                         palette_cmap.blue[j] = clut[2] << 8 | clut[2];
     226                 :          0 :                         clut += 3;
     227                 :            :                 }
     228                 :          0 :                 fb_set_cmap(&palette_cmap, info);
     229                 :            :         }
     230                 :          0 : }
     231                 :            : 
     232                 :          0 : static void  fb_set_logo_truepalette(struct fb_info *info,
     233                 :            :                                             const struct linux_logo *logo,
     234                 :            :                                             u32 *palette)
     235                 :            : {
     236                 :            :         static const unsigned char mask[] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
     237                 :            :         unsigned char redmask, greenmask, bluemask;
     238                 :            :         int redshift, greenshift, blueshift;
     239                 :            :         int i;
     240                 :          0 :         const unsigned char *clut = logo->clut;
     241                 :            : 
     242                 :            :         /*
     243                 :            :          * We have to create a temporary palette since console palette is only
     244                 :            :          * 16 colors long.
     245                 :            :          */
     246                 :            :         /* Bug: Doesn't obey msb_right ... (who needs that?) */
     247                 :          0 :         redmask   = mask[info->var.red.length   < 8 ? info->var.red.length   : 8];
     248                 :          0 :         greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
     249                 :          0 :         bluemask  = mask[info->var.blue.length  < 8 ? info->var.blue.length  : 8];
     250                 :          0 :         redshift   = info->var.red.offset   - (8 - info->var.red.length);
     251                 :          0 :         greenshift = info->var.green.offset - (8 - info->var.green.length);
     252                 :          0 :         blueshift  = info->var.blue.offset  - (8 - info->var.blue.length);
     253                 :            : 
     254         [ #  # ]:          0 :         for ( i = 0; i < logo->clutsize; i++) {
     255                 :          0 :                 palette[i+32] = (safe_shift((clut[0] & redmask), redshift) |
     256                 :          0 :                                  safe_shift((clut[1] & greenmask), greenshift) |
     257                 :          0 :                                  safe_shift((clut[2] & bluemask), blueshift));
     258                 :          0 :                 clut += 3;
     259                 :            :         }
     260                 :          0 : }
     261                 :            : 
     262                 :            : static void fb_set_logo_directpalette(struct fb_info *info,
     263                 :            :                                              const struct linux_logo *logo,
     264                 :            :                                              u32 *palette)
     265                 :            : {
     266                 :            :         int redshift, greenshift, blueshift;
     267                 :            :         int i;
     268                 :            : 
     269                 :          0 :         redshift = info->var.red.offset;
     270                 :          0 :         greenshift = info->var.green.offset;
     271                 :          0 :         blueshift = info->var.blue.offset;
     272                 :            : 
     273         [ #  # ]:          0 :         for (i = 32; i < 32 + logo->clutsize; i++)
     274                 :          0 :                 palette[i] = i << redshift | i << greenshift | i << blueshift;
     275                 :            : }
     276                 :            : 
     277                 :          0 : static void fb_set_logo(struct fb_info *info,
     278                 :            :                                const struct linux_logo *logo, u8 *dst,
     279                 :            :                                int depth)
     280                 :            : {
     281                 :            :         int i, j, k;
     282                 :          0 :         const u8 *src = logo->data;
     283         [ #  # ]:          0 :         u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
     284                 :            :         u8 fg = 1, d;
     285                 :            : 
     286      [ #  #  # ]:          0 :         switch (fb_get_color_depth(&info->var, &info->fix)) {
     287                 :            :         case 1:
     288                 :            :                 fg = 1;
     289                 :            :                 break;
     290                 :            :         case 2:
     291                 :            :                 fg = 3;
     292                 :          0 :                 break;
     293                 :            :         default:
     294                 :            :                 fg = 7;
     295                 :          0 :                 break;
     296                 :            :         }
     297                 :            : 
     298         [ #  # ]:          0 :         if (info->fix.visual == FB_VISUAL_MONO01 ||
     299                 :            :             info->fix.visual == FB_VISUAL_MONO10)
     300                 :          0 :                 fg = ~((u8) (0xfff << info->var.green.length));
     301                 :            : 
     302      [ #  #  # ]:          0 :         switch (depth) {
     303                 :            :         case 4:
     304         [ #  # ]:          0 :                 for (i = 0; i < logo->height; i++)
     305         [ #  # ]:          0 :                         for (j = 0; j < logo->width; src++) {
     306                 :          0 :                                 *dst++ = *src >> 4;
     307                 :          0 :                                 j++;
     308         [ #  # ]:          0 :                                 if (j < logo->width) {
     309                 :          0 :                                         *dst++ = *src & 0x0f;
     310                 :          0 :                                         j++;
     311                 :            :                                 }
     312                 :            :                         }
     313                 :            :                 break;
     314                 :            :         case 1:
     315         [ #  # ]:          0 :                 for (i = 0; i < logo->height; i++) {
     316         [ #  # ]:          0 :                         for (j = 0; j < logo->width; src++) {
     317                 :          0 :                                 d = *src ^ xor;
     318         [ #  # ]:          0 :                                 for (k = 7; k >= 0; k--) {
     319         [ #  # ]:          0 :                                         *dst++ = ((d >> k) & 1) ? fg : 0;
     320                 :          0 :                                         j++;
     321                 :            :                                 }
     322                 :            :                         }
     323                 :            :                 }
     324                 :            :                 break;
     325                 :            :         }
     326                 :          0 : }
     327                 :            : 
     328                 :            : /*
     329                 :            :  * Three (3) kinds of logo maps exist.  linux_logo_clut224 (>16 colors),
     330                 :            :  * linux_logo_vga16 (16 colors) and linux_logo_mono (2 colors).  Depending on
     331                 :            :  * the visual format and color depth of the framebuffer, the DAC, the
     332                 :            :  * pseudo_palette, and the logo data will be adjusted accordingly.
     333                 :            :  *
     334                 :            :  * Case 1 - linux_logo_clut224:
     335                 :            :  * Color exceeds the number of console colors (16), thus we set the hardware DAC
     336                 :            :  * using fb_set_cmap() appropriately.  The "needs_cmapreset"  flag will be set.
     337                 :            :  *
     338                 :            :  * For visuals that require color info from the pseudo_palette, we also construct
     339                 :            :  * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
     340                 :            :  * will be set.
     341                 :            :  *
     342                 :            :  * Case 2 - linux_logo_vga16:
     343                 :            :  * The number of colors just matches the console colors, thus there is no need
     344                 :            :  * to set the DAC or the pseudo_palette.  However, the bitmap is packed, ie,
     345                 :            :  * each byte contains color information for two pixels (upper and lower nibble).
     346                 :            :  * To be consistent with fb_imageblit() usage, we therefore separate the two
     347                 :            :  * nibbles into separate bytes. The "depth" flag will be set to 4.
     348                 :            :  *
     349                 :            :  * Case 3 - linux_logo_mono:
     350                 :            :  * This is similar with Case 2.  Each byte contains information for 8 pixels.
     351                 :            :  * We isolate each bit and expand each into a byte. The "depth" flag will
     352                 :            :  * be set to 1.
     353                 :            :  */
     354                 :            : static struct logo_data {
     355                 :            :         int depth;
     356                 :            :         int needs_directpalette;
     357                 :            :         int needs_truepalette;
     358                 :            :         int needs_cmapreset;
     359                 :            :         const struct linux_logo *logo;
     360                 :            : } fb_logo __read_mostly;
     361                 :            : 
     362                 :            : static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height)
     363                 :            : {
     364                 :          0 :         u32 size = width * height, i;
     365                 :            : 
     366                 :          0 :         out += size - 1;
     367                 :            : 
     368         [ #  # ]:          0 :         for (i = size; i--; )
     369                 :          0 :                 *out-- = *in++;
     370                 :            : }
     371                 :            : 
     372                 :            : static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height)
     373                 :            : {
     374                 :          0 :         int i, j, h = height - 1;
     375                 :            : 
     376         [ #  # ]:          0 :         for (i = 0; i < height; i++)
     377         [ #  # ]:          0 :                 for (j = 0; j < width; j++)
     378                 :          0 :                                 out[height * j + h - i] = *in++;
     379                 :            : }
     380                 :            : 
     381                 :            : static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height)
     382                 :            : {
     383                 :          0 :         int i, j, w = width - 1;
     384                 :            : 
     385         [ #  # ]:          0 :         for (i = 0; i < height; i++)
     386         [ #  # ]:          0 :                 for (j = 0; j < width; j++)
     387                 :          0 :                         out[height * (w - j) + i] = *in++;
     388                 :            : }
     389                 :            : 
     390                 :          0 : static void fb_rotate_logo(struct fb_info *info, u8 *dst,
     391                 :            :                            struct fb_image *image, int rotate)
     392                 :            : {
     393                 :            :         u32 tmp;
     394                 :            : 
     395         [ #  # ]:          0 :         if (rotate == FB_ROTATE_UD) {
     396                 :          0 :                 fb_rotate_logo_ud(image->data, dst, image->width,
     397                 :            :                                   image->height);
     398                 :          0 :                 image->dx = info->var.xres - image->width - image->dx;
     399                 :          0 :                 image->dy = info->var.yres - image->height - image->dy;
     400         [ #  # ]:          0 :         } else if (rotate == FB_ROTATE_CW) {
     401                 :          0 :                 fb_rotate_logo_cw(image->data, dst, image->width,
     402                 :            :                                   image->height);
     403                 :          0 :                 tmp = image->width;
     404                 :          0 :                 image->width = image->height;
     405                 :          0 :                 image->height = tmp;
     406                 :          0 :                 tmp = image->dy;
     407                 :          0 :                 image->dy = image->dx;
     408                 :          0 :                 image->dx = info->var.xres - image->width - tmp;
     409         [ #  # ]:          0 :         } else if (rotate == FB_ROTATE_CCW) {
     410                 :          0 :                 fb_rotate_logo_ccw(image->data, dst, image->width,
     411                 :            :                                    image->height);
     412                 :          0 :                 tmp = image->width;
     413                 :          0 :                 image->width = image->height;
     414                 :          0 :                 image->height = tmp;
     415                 :          0 :                 tmp = image->dx;
     416                 :          0 :                 image->dx = image->dy;
     417                 :          0 :                 image->dy = info->var.yres - image->height - tmp;
     418                 :            :         }
     419                 :            : 
     420                 :          0 :         image->data = dst;
     421                 :          0 : }
     422                 :            : 
     423                 :          0 : static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
     424                 :            :                             int rotate, unsigned int num)
     425                 :            : {
     426                 :            :         unsigned int x;
     427                 :            : 
     428         [ #  # ]:          0 :         if (rotate == FB_ROTATE_UR) {
     429         [ #  # ]:          0 :                 for (x = 0;
     430         [ #  # ]:          0 :                      x < num && image->dx + image->width <= info->var.xres;
     431                 :          0 :                      x++) {
     432                 :          0 :                         info->fbops->fb_imageblit(info, image);
     433                 :          0 :                         image->dx += image->width + 8;
     434                 :            :                 }
     435         [ #  # ]:          0 :         } else if (rotate == FB_ROTATE_UD) {
     436         [ #  # ]:          0 :                 for (x = 0; x < num && image->dx >= 0; x++) {
     437                 :          0 :                         info->fbops->fb_imageblit(info, image);
     438                 :          0 :                         image->dx -= image->width + 8;
     439                 :            :                 }
     440         [ #  # ]:          0 :         } else if (rotate == FB_ROTATE_CW) {
     441         [ #  # ]:          0 :                 for (x = 0;
     442         [ #  # ]:          0 :                      x < num && image->dy + image->height <= info->var.yres;
     443                 :          0 :                      x++) {
     444                 :          0 :                         info->fbops->fb_imageblit(info, image);
     445                 :          0 :                         image->dy += image->height + 8;
     446                 :            :                 }
     447         [ #  # ]:          0 :         } else if (rotate == FB_ROTATE_CCW) {
     448         [ #  # ]:          0 :                 for (x = 0; x < num && image->dy >= 0; x++) {
     449                 :          0 :                         info->fbops->fb_imageblit(info, image);
     450                 :          0 :                         image->dy -= image->height + 8;
     451                 :            :                 }
     452                 :            :         }
     453                 :          0 : }
     454                 :            : 
     455                 :          0 : static int fb_show_logo_line(struct fb_info *info, int rotate,
     456                 :          0 :                              const struct linux_logo *logo, int y,
     457                 :            :                              unsigned int n)
     458                 :            : {
     459                 :            :         u32 *palette = NULL, *saved_pseudo_palette = NULL;
     460                 :            :         unsigned char *logo_new = NULL, *logo_rotate = NULL;
     461                 :            :         struct fb_image image;
     462                 :            : 
     463                 :            :         /* Return if the frame buffer is not mapped or suspended */
     464 [ #  # ][ #  # ]:          0 :         if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||
                 [ #  # ]
     465                 :          0 :             info->flags & FBINFO_MODULE)
     466                 :            :                 return 0;
     467                 :            : 
     468                 :          0 :         image.depth = 8;
     469                 :          0 :         image.data = logo->data;
     470                 :            : 
     471         [ #  # ]:          0 :         if (fb_logo.needs_cmapreset)
     472                 :          0 :                 fb_set_logocmap(info, logo);
     473                 :            : 
     474 [ #  # ][ #  # ]:          0 :         if (fb_logo.needs_truepalette ||
     475                 :          0 :             fb_logo.needs_directpalette) {
     476                 :            :                 palette = kmalloc(256 * 4, GFP_KERNEL);
     477         [ #  # ]:          0 :                 if (palette == NULL)
     478                 :            :                         return 0;
     479                 :            : 
     480         [ #  # ]:          0 :                 if (fb_logo.needs_truepalette)
     481                 :          0 :                         fb_set_logo_truepalette(info, logo, palette);
     482                 :            :                 else
     483                 :            :                         fb_set_logo_directpalette(info, logo, palette);
     484                 :            : 
     485                 :          0 :                 saved_pseudo_palette = info->pseudo_palette;
     486                 :          0 :                 info->pseudo_palette = palette;
     487                 :            :         }
     488                 :            : 
     489         [ #  # ]:          0 :         if (fb_logo.depth <= 4) {
     490                 :          0 :                 logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);
     491         [ #  # ]:          0 :                 if (logo_new == NULL) {
     492                 :          0 :                         kfree(palette);
     493         [ #  # ]:          0 :                         if (saved_pseudo_palette)
     494                 :          0 :                                 info->pseudo_palette = saved_pseudo_palette;
     495                 :            :                         return 0;
     496                 :            :                 }
     497                 :          0 :                 image.data = logo_new;
     498                 :          0 :                 fb_set_logo(info, logo, logo_new, fb_logo.depth);
     499                 :            :         }
     500                 :            : 
     501                 :          0 :         image.dx = 0;
     502                 :          0 :         image.dy = y;
     503                 :          0 :         image.width = logo->width;
     504                 :          0 :         image.height = logo->height;
     505                 :            : 
     506         [ #  # ]:          0 :         if (rotate) {
     507                 :          0 :                 logo_rotate = kmalloc(logo->width *
     508                 :            :                                       logo->height, GFP_KERNEL);
     509         [ #  # ]:          0 :                 if (logo_rotate)
     510                 :          0 :                         fb_rotate_logo(info, logo_rotate, &image, rotate);
     511                 :            :         }
     512                 :            : 
     513                 :          0 :         fb_do_show_logo(info, &image, rotate, n);
     514                 :            : 
     515                 :          0 :         kfree(palette);
     516         [ #  # ]:          0 :         if (saved_pseudo_palette != NULL)
     517                 :          0 :                 info->pseudo_palette = saved_pseudo_palette;
     518                 :          0 :         kfree(logo_new);
     519                 :          0 :         kfree(logo_rotate);
     520                 :          0 :         return logo->height;
     521                 :            : }
     522                 :            : 
     523                 :            : 
     524                 :            : #ifdef CONFIG_FB_LOGO_EXTRA
     525                 :            : 
     526                 :            : #define FB_LOGO_EX_NUM_MAX 10
     527                 :            : static struct logo_data_extra {
     528                 :            :         const struct linux_logo *logo;
     529                 :            :         unsigned int n;
     530                 :            : } fb_logo_ex[FB_LOGO_EX_NUM_MAX];
     531                 :            : static unsigned int fb_logo_ex_num;
     532                 :            : 
     533                 :            : void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n)
     534                 :            : {
     535                 :            :         if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX)
     536                 :            :                 return;
     537                 :            : 
     538                 :            :         fb_logo_ex[fb_logo_ex_num].logo = logo;
     539                 :            :         fb_logo_ex[fb_logo_ex_num].n = n;
     540                 :            :         fb_logo_ex_num++;
     541                 :            : }
     542                 :            : 
     543                 :            : static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height,
     544                 :            :                                   unsigned int yres)
     545                 :            : {
     546                 :            :         unsigned int i;
     547                 :            : 
     548                 :            :         /* FIXME: logo_ex supports only truecolor fb. */
     549                 :            :         if (info->fix.visual != FB_VISUAL_TRUECOLOR)
     550                 :            :                 fb_logo_ex_num = 0;
     551                 :            : 
     552                 :            :         for (i = 0; i < fb_logo_ex_num; i++) {
     553                 :            :                 if (fb_logo_ex[i].logo->type != fb_logo.logo->type) {
     554                 :            :                         fb_logo_ex[i].logo = NULL;
     555                 :            :                         continue;
     556                 :            :                 }
     557                 :            :                 height += fb_logo_ex[i].logo->height;
     558                 :            :                 if (height > yres) {
     559                 :            :                         height -= fb_logo_ex[i].logo->height;
     560                 :            :                         fb_logo_ex_num = i;
     561                 :            :                         break;
     562                 :            :                 }
     563                 :            :         }
     564                 :            :         return height;
     565                 :            : }
     566                 :            : 
     567                 :            : static int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
     568                 :            : {
     569                 :            :         unsigned int i;
     570                 :            : 
     571                 :            :         for (i = 0; i < fb_logo_ex_num; i++)
     572                 :            :                 y += fb_show_logo_line(info, rotate,
     573                 :            :                                        fb_logo_ex[i].logo, y, fb_logo_ex[i].n);
     574                 :            : 
     575                 :            :         return y;
     576                 :            : }
     577                 :            : 
     578                 :            : #else /* !CONFIG_FB_LOGO_EXTRA */
     579                 :            : 
     580                 :            : static inline int fb_prepare_extra_logos(struct fb_info *info,
     581                 :            :                                          unsigned int height,
     582                 :            :                                          unsigned int yres)
     583                 :            : {
     584                 :          0 :         return height;
     585                 :            : }
     586                 :            : 
     587                 :            : static inline int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
     588                 :            : {
     589                 :            :         return y;
     590                 :            : }
     591                 :            : 
     592                 :            : #endif /* CONFIG_FB_LOGO_EXTRA */
     593                 :            : 
     594                 :            : 
     595                 :          0 : int fb_prepare_logo(struct fb_info *info, int rotate)
     596                 :            : {
     597                 :          0 :         int depth = fb_get_color_depth(&info->var, &info->fix);
     598                 :            :         unsigned int yres;
     599                 :            : 
     600                 :          0 :         memset(&fb_logo, 0, sizeof(struct logo_data));
     601                 :            : 
     602         [ #  # ]:          0 :         if (info->flags & FBINFO_MISC_TILEBLITTING ||
     603                 :            :             info->flags & FBINFO_MODULE)
     604                 :            :                 return 0;
     605                 :            : 
     606         [ #  # ]:          0 :         if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
     607                 :          0 :                 depth = info->var.blue.length;
     608         [ #  # ]:          0 :                 if (info->var.red.length < depth)
     609                 :          0 :                         depth = info->var.red.length;
     610         [ #  # ]:          0 :                 if (info->var.green.length < depth)
     611                 :          0 :                         depth = info->var.green.length;
     612                 :            :         }
     613                 :            : 
     614 [ #  # ][ #  # ]:          0 :         if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) {
     615                 :            :                 /* assume console colormap */
     616                 :            :                 depth = 4;
     617                 :            :         }
     618                 :            : 
     619                 :            :         /* Return if no suitable logo was found */
     620                 :          0 :         fb_logo.logo = fb_find_logo(depth);
     621                 :            : 
     622         [ #  # ]:          0 :         if (!fb_logo.logo) {
     623                 :            :                 return 0;
     624                 :            :         }
     625                 :            : 
     626         [ #  # ]:          0 :         if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
     627                 :          0 :                 yres = info->var.yres;
     628                 :            :         else
     629                 :          0 :                 yres = info->var.xres;
     630                 :            : 
     631         [ #  # ]:          0 :         if (fb_logo.logo->height > yres) {
     632                 :          0 :                 fb_logo.logo = NULL;
     633                 :          0 :                 return 0;
     634                 :            :         }
     635                 :            : 
     636                 :            :         /* What depth we asked for might be different from what we get */
     637         [ #  # ]:          0 :         if (fb_logo.logo->type == LINUX_LOGO_CLUT224)
     638                 :          0 :                 fb_logo.depth = 8;
     639         [ #  # ]:          0 :         else if (fb_logo.logo->type == LINUX_LOGO_VGA16)
     640                 :          0 :                 fb_logo.depth = 4;
     641                 :            :         else
     642                 :          0 :                 fb_logo.depth = 1;
     643                 :            : 
     644                 :            : 
     645 [ #  # ][ #  # ]:          0 :         if (fb_logo.depth > 4 && depth > 4) {
     646   [ #  #  #  # ]:          0 :                 switch (info->fix.visual) {
     647                 :            :                 case FB_VISUAL_TRUECOLOR:
     648                 :          0 :                         fb_logo.needs_truepalette = 1;
     649                 :          0 :                         break;
     650                 :            :                 case FB_VISUAL_DIRECTCOLOR:
     651                 :          0 :                         fb_logo.needs_directpalette = 1;
     652                 :          0 :                         fb_logo.needs_cmapreset = 1;
     653                 :          0 :                         break;
     654                 :            :                 case FB_VISUAL_PSEUDOCOLOR:
     655                 :          0 :                         fb_logo.needs_cmapreset = 1;
     656                 :          0 :                         break;
     657                 :            :                 }
     658                 :            :         }
     659                 :            : 
     660                 :          0 :         return fb_prepare_extra_logos(info, fb_logo.logo->height, yres);
     661                 :            : }
     662                 :            : 
     663                 :          0 : int fb_show_logo(struct fb_info *info, int rotate)
     664                 :            : {
     665                 :            :         int y;
     666                 :            : 
     667                 :          0 :         y = fb_show_logo_line(info, rotate, fb_logo.logo, 0,
     668                 :            :                               num_online_cpus());
     669                 :            :         y = fb_show_extra_logos(info, y, rotate);
     670                 :            : 
     671                 :          0 :         return y;
     672                 :            : }
     673                 :            : #else
     674                 :            : int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; }
     675                 :            : int fb_show_logo(struct fb_info *info, int rotate) { return 0; }
     676                 :            : #endif /* CONFIG_LOGO */
     677                 :            : EXPORT_SYMBOL(fb_show_logo);
     678                 :            : 
     679                 :          0 : static void *fb_seq_start(struct seq_file *m, loff_t *pos)
     680                 :            : {
     681                 :          2 :         mutex_lock(&registration_lock);
     682         [ +  + ]:          2 :         return (*pos < FB_MAX) ? pos : NULL;
     683                 :            : }
     684                 :            : 
     685                 :          0 : static void *fb_seq_next(struct seq_file *m, void *v, loff_t *pos)
     686                 :            : {
     687                 :         32 :         (*pos)++;
     688         [ +  + ]:         32 :         return (*pos < FB_MAX) ? pos : NULL;
     689                 :            : }
     690                 :            : 
     691                 :          0 : static void fb_seq_stop(struct seq_file *m, void *v)
     692                 :            : {
     693                 :          2 :         mutex_unlock(&registration_lock);
     694                 :          2 : }
     695                 :            : 
     696                 :          0 : static int fb_seq_show(struct seq_file *m, void *v)
     697                 :            : {
     698                 :         32 :         int i = *(loff_t *)v;
     699                 :         32 :         struct fb_info *fi = registered_fb[i];
     700                 :            : 
     701         [ +  + ]:         32 :         if (fi)
     702                 :          1 :                 seq_printf(m, "%d %s\n", fi->node, fi->fix.id);
     703                 :          0 :         return 0;
     704                 :            : }
     705                 :            : 
     706                 :            : static const struct seq_operations proc_fb_seq_ops = {
     707                 :            :         .start  = fb_seq_start,
     708                 :            :         .next   = fb_seq_next,
     709                 :            :         .stop   = fb_seq_stop,
     710                 :            :         .show   = fb_seq_show,
     711                 :            : };
     712                 :            : 
     713                 :          0 : static int proc_fb_open(struct inode *inode, struct file *file)
     714                 :            : {
     715                 :          1 :         return seq_open(file, &proc_fb_seq_ops);
     716                 :            : }
     717                 :            : 
     718                 :            : static const struct file_operations fb_proc_fops = {
     719                 :            :         .owner          = THIS_MODULE,
     720                 :            :         .open           = proc_fb_open,
     721                 :            :         .read           = seq_read,
     722                 :            :         .llseek         = seq_lseek,
     723                 :            :         .release        = seq_release,
     724                 :            : };
     725                 :            : 
     726                 :            : /*
     727                 :            :  * We hold a reference to the fb_info in file->private_data,
     728                 :            :  * but if the current registered fb has changed, we don't
     729                 :            :  * actually want to use it.
     730                 :            :  *
     731                 :            :  * So look up the fb_info using the inode minor number,
     732                 :            :  * and just verify it against the reference we have.
     733                 :            :  */
     734                 :          0 : static struct fb_info *file_fb_info(struct file *file)
     735                 :            : {
     736                 :          0 :         struct inode *inode = file_inode(file);
     737                 :          0 :         int fbidx = iminor(inode);
     738                 :          0 :         struct fb_info *info = registered_fb[fbidx];
     739                 :            : 
     740 [ #  # ][ #  # ]:          0 :         if (info != file->private_data)
         [ #  # ][ #  # ]
     741                 :            :                 info = NULL;
     742                 :            :         return info;
     743                 :            : }
     744                 :            : 
     745                 :            : static ssize_t
     746                 :          0 : fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
     747                 :            : {
     748                 :          0 :         unsigned long p = *ppos;
     749                 :            :         struct fb_info *info = file_fb_info(file);
     750                 :            :         u8 *buffer, *dst;
     751                 :            :         u8 __iomem *src;
     752                 :            :         int c, cnt = 0, err = 0;
     753                 :            :         unsigned long total_size;
     754                 :            : 
     755 [ #  # ][ #  # ]:          0 :         if (!info || ! info->screen_base)
     756                 :            :                 return -ENODEV;
     757                 :            : 
     758         [ #  # ]:          0 :         if (info->state != FBINFO_STATE_RUNNING)
     759                 :            :                 return -EPERM;
     760                 :            : 
     761         [ #  # ]:          0 :         if (info->fbops->fb_read)
     762                 :          0 :                 return info->fbops->fb_read(info, buf, count, ppos);
     763                 :            :         
     764                 :          0 :         total_size = info->screen_size;
     765                 :            : 
     766         [ #  # ]:          0 :         if (total_size == 0)
     767                 :          0 :                 total_size = info->fix.smem_len;
     768                 :            : 
     769         [ #  # ]:          0 :         if (p >= total_size)
     770                 :            :                 return 0;
     771                 :            : 
     772         [ #  # ]:          0 :         if (count >= total_size)
     773                 :            :                 count = total_size;
     774                 :            : 
     775         [ #  # ]:          0 :         if (count + p > total_size)
     776                 :          0 :                 count = total_size - p;
     777                 :            : 
     778                 :          0 :         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
     779                 :            :                          GFP_KERNEL);
     780         [ #  # ]:          0 :         if (!buffer)
     781                 :            :                 return -ENOMEM;
     782                 :            : 
     783                 :          0 :         src = (u8 __iomem *) (info->screen_base + p);
     784                 :            : 
     785         [ #  # ]:          0 :         if (info->fbops->fb_sync)
     786                 :          0 :                 info->fbops->fb_sync(info);
     787                 :            : 
     788         [ #  # ]:          0 :         while (count) {
     789                 :          0 :                 c  = (count > PAGE_SIZE) ? PAGE_SIZE : count;
     790                 :            :                 dst = buffer;
     791                 :          0 :                 fb_memcpy_fromfb(dst, src, c);
     792                 :            :                 dst += c;
     793                 :          0 :                 src += c;
     794                 :            : 
     795         [ #  # ]:          0 :                 if (copy_to_user(buf, buffer, c)) {
     796                 :            :                         err = -EFAULT;
     797                 :            :                         break;
     798                 :            :                 }
     799                 :          0 :                 *ppos += c;
     800                 :          0 :                 buf += c;
     801                 :          0 :                 cnt += c;
     802                 :          0 :                 count -= c;
     803                 :            :         }
     804                 :            : 
     805                 :          0 :         kfree(buffer);
     806                 :            : 
     807         [ #  # ]:          0 :         return (err) ? err : cnt;
     808                 :            : }
     809                 :            : 
     810                 :            : static ssize_t
     811                 :          0 : fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
     812                 :            : {
     813                 :          0 :         unsigned long p = *ppos;
     814                 :            :         struct fb_info *info = file_fb_info(file);
     815                 :            :         u8 *buffer, *src;
     816                 :            :         u8 __iomem *dst;
     817                 :            :         int c, cnt = 0, err = 0;
     818                 :            :         unsigned long total_size;
     819                 :            : 
     820 [ #  # ][ #  # ]:          0 :         if (!info || !info->screen_base)
     821                 :            :                 return -ENODEV;
     822                 :            : 
     823         [ #  # ]:          0 :         if (info->state != FBINFO_STATE_RUNNING)
     824                 :            :                 return -EPERM;
     825                 :            : 
     826         [ #  # ]:          0 :         if (info->fbops->fb_write)
     827                 :          0 :                 return info->fbops->fb_write(info, buf, count, ppos);
     828                 :            :         
     829                 :          0 :         total_size = info->screen_size;
     830                 :            : 
     831         [ #  # ]:          0 :         if (total_size == 0)
     832                 :          0 :                 total_size = info->fix.smem_len;
     833                 :            : 
     834         [ #  # ]:          0 :         if (p > total_size)
     835                 :            :                 return -EFBIG;
     836                 :            : 
     837         [ #  # ]:          0 :         if (count > total_size) {
     838                 :            :                 err = -EFBIG;
     839                 :            :                 count = total_size;
     840                 :            :         }
     841                 :            : 
     842         [ #  # ]:          0 :         if (count + p > total_size) {
     843         [ #  # ]:          0 :                 if (!err)
     844                 :            :                         err = -ENOSPC;
     845                 :            : 
     846                 :          0 :                 count = total_size - p;
     847                 :            :         }
     848                 :            : 
     849                 :          0 :         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
     850                 :            :                          GFP_KERNEL);
     851         [ #  # ]:          0 :         if (!buffer)
     852                 :            :                 return -ENOMEM;
     853                 :            : 
     854                 :          0 :         dst = (u8 __iomem *) (info->screen_base + p);
     855                 :            : 
     856         [ #  # ]:          0 :         if (info->fbops->fb_sync)
     857                 :          0 :                 info->fbops->fb_sync(info);
     858                 :            : 
     859         [ #  # ]:          0 :         while (count) {
     860                 :          0 :                 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
     861                 :            :                 src = buffer;
     862                 :            : 
     863         [ #  # ]:          0 :                 if (copy_from_user(src, buf, c)) {
     864                 :            :                         err = -EFAULT;
     865                 :            :                         break;
     866                 :            :                 }
     867                 :            : 
     868                 :          0 :                 fb_memcpy_tofb(dst, src, c);
     869                 :          0 :                 dst += c;
     870                 :            :                 src += c;
     871                 :          0 :                 *ppos += c;
     872                 :          0 :                 buf += c;
     873                 :          0 :                 cnt += c;
     874                 :          0 :                 count -= c;
     875                 :            :         }
     876                 :            : 
     877                 :          0 :         kfree(buffer);
     878                 :            : 
     879         [ #  # ]:          0 :         return (cnt) ? cnt : err;
     880                 :            : }
     881                 :            : 
     882                 :            : int
     883                 :          0 : fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
     884                 :            : {
     885                 :            :         struct fb_fix_screeninfo *fix = &info->fix;
     886                 :          0 :         unsigned int yres = info->var.yres;
     887                 :            :         int err = 0;
     888                 :            : 
     889         [ #  # ]:          0 :         if (var->yoffset > 0) {
     890         [ #  # ]:          0 :                 if (var->vmode & FB_VMODE_YWRAP) {
     891 [ #  # ][ #  # ]:          0 :                         if (!fix->ywrapstep || (var->yoffset % fix->ywrapstep))
     892                 :            :                                 err = -EINVAL;
     893                 :            :                         else
     894                 :            :                                 yres = 0;
     895 [ #  # ][ #  # ]:          0 :                 } else if (!fix->ypanstep || (var->yoffset % fix->ypanstep))
     896                 :            :                         err = -EINVAL;
     897                 :            :         }
     898                 :            : 
     899 [ #  # ][ #  # ]:          0 :         if (var->xoffset > 0 && (!fix->xpanstep ||
                 [ #  # ]
     900                 :          0 :                                  (var->xoffset % fix->xpanstep)))
     901                 :            :                 err = -EINVAL;
     902                 :            : 
     903 [ #  # ][ #  # ]:          0 :         if (err || !info->fbops->fb_pan_display ||
                 [ #  # ]
     904         [ #  # ]:          0 :             var->yoffset > info->var.yres_virtual - yres ||
     905                 :          0 :             var->xoffset > info->var.xres_virtual - info->var.xres)
     906                 :            :                 return -EINVAL;
     907                 :            : 
     908         [ #  # ]:          0 :         if ((err = info->fbops->fb_pan_display(var, info)))
     909                 :            :                 return err;
     910                 :          0 :         info->var.xoffset = var->xoffset;
     911                 :          0 :         info->var.yoffset = var->yoffset;
     912         [ #  # ]:          0 :         if (var->vmode & FB_VMODE_YWRAP)
     913                 :          0 :                 info->var.vmode |= FB_VMODE_YWRAP;
     914                 :            :         else
     915                 :          0 :                 info->var.vmode &= ~FB_VMODE_YWRAP;
     916                 :            :         return 0;
     917                 :            : }
     918                 :            : EXPORT_SYMBOL(fb_pan_display);
     919                 :            : 
     920                 :          0 : static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
     921                 :            :                          u32 activate)
     922                 :            : {
     923                 :            :         struct fb_event event;
     924                 :            :         struct fb_blit_caps caps, fbcaps;
     925                 :            :         int err = 0;
     926                 :            : 
     927                 :          0 :         memset(&caps, 0, sizeof(caps));
     928                 :          0 :         memset(&fbcaps, 0, sizeof(fbcaps));
     929                 :          0 :         caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0;
     930                 :          0 :         event.info = info;
     931                 :          0 :         event.data = &caps;
     932                 :          0 :         fb_notifier_call_chain(FB_EVENT_GET_REQ, &event);
     933                 :          0 :         info->fbops->fb_get_caps(info, &fbcaps, var);
     934                 :            : 
     935 [ #  # ][ #  # ]:          0 :         if (((fbcaps.x ^ caps.x) & caps.x) ||
     936         [ #  # ]:          0 :             ((fbcaps.y ^ caps.y) & caps.y) ||
     937                 :          0 :             (fbcaps.len < caps.len))
     938                 :            :                 err = -EINVAL;
     939                 :            : 
     940                 :          0 :         return err;
     941                 :            : }
     942                 :            : 
     943                 :            : int
     944                 :          0 : fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
     945                 :            : {
     946                 :          0 :         int flags = info->flags;
     947                 :            :         int ret = 0;
     948                 :            : 
     949         [ #  # ]:          0 :         if (var->activate & FB_ACTIVATE_INV_MODE) {
     950                 :            :                 struct fb_videomode mode1, mode2;
     951                 :            : 
     952                 :          0 :                 fb_var_to_videomode(&mode1, var);
     953                 :          0 :                 fb_var_to_videomode(&mode2, &info->var);
     954                 :            :                 /* make sure we don't delete the videomode of current var */
     955                 :          0 :                 ret = fb_mode_is_equal(&mode1, &mode2);
     956                 :            : 
     957         [ #  # ]:          0 :                 if (!ret) {
     958                 :            :                     struct fb_event event;
     959                 :            : 
     960                 :          0 :                     event.info = info;
     961                 :          0 :                     event.data = &mode1;
     962                 :          0 :                     ret = fb_notifier_call_chain(FB_EVENT_MODE_DELETE, &event);
     963                 :            :                 }
     964                 :            : 
     965         [ #  # ]:          0 :                 if (!ret)
     966                 :          0 :                     fb_delete_videomode(&mode1, &info->modelist);
     967                 :            : 
     968                 :            : 
     969         [ #  # ]:          0 :                 ret = (ret) ? -EINVAL : 0;
     970                 :            :                 goto done;
     971                 :            :         }
     972                 :            : 
     973 [ #  # ][ #  # ]:          0 :         if ((var->activate & FB_ACTIVATE_FORCE) ||
     974                 :          0 :             memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
     975                 :            :                 u32 activate = var->activate;
     976                 :            : 
     977                 :            :                 /* When using FOURCC mode, make sure the red, green, blue and
     978                 :            :                  * transp fields are set to 0.
     979                 :            :                  */
     980 [ #  # ][ #  # ]:          0 :                 if ((info->fix.capabilities & FB_CAP_FOURCC) &&
     981                 :          0 :                     var->grayscale > 1) {
     982 [ #  # ][ #  # ]:          0 :                         if (var->red.offset     || var->green.offset    ||
                 [ #  # ]
     983 [ #  # ][ #  # ]:          0 :                             var->blue.offset    || var->transp.offset   ||
     984 [ #  # ][ #  # ]:          0 :                             var->red.length     || var->green.length    ||
     985 [ #  # ][ #  # ]:          0 :                             var->blue.length    || var->transp.length   ||
     986 [ #  # ][ #  # ]:          0 :                             var->red.msb_right  || var->green.msb_right ||
     987         [ #  # ]:          0 :                             var->blue.msb_right || var->transp.msb_right)
     988                 :            :                                 return -EINVAL;
     989                 :            :                 }
     990                 :            : 
     991         [ #  # ]:          0 :                 if (!info->fbops->fb_check_var) {
     992                 :          0 :                         *var = info->var;
     993                 :          0 :                         goto done;
     994                 :            :                 }
     995                 :            : 
     996                 :          0 :                 ret = info->fbops->fb_check_var(var, info);
     997                 :            : 
     998         [ #  # ]:          0 :                 if (ret)
     999                 :            :                         goto done;
    1000                 :            : 
    1001         [ #  # ]:          0 :                 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
    1002                 :            :                         struct fb_var_screeninfo old_var;
    1003                 :            :                         struct fb_videomode mode;
    1004                 :            : 
    1005         [ #  # ]:          0 :                         if (info->fbops->fb_get_caps) {
    1006                 :          0 :                                 ret = fb_check_caps(info, var, activate);
    1007                 :            : 
    1008         [ #  # ]:          0 :                                 if (ret)
    1009                 :            :                                         goto done;
    1010                 :            :                         }
    1011                 :            : 
    1012                 :          0 :                         old_var = info->var;
    1013                 :          0 :                         info->var = *var;
    1014                 :            : 
    1015         [ #  # ]:          0 :                         if (info->fbops->fb_set_par) {
    1016                 :          0 :                                 ret = info->fbops->fb_set_par(info);
    1017                 :            : 
    1018         [ #  # ]:          0 :                                 if (ret) {
    1019                 :          0 :                                         info->var = old_var;
    1020                 :          0 :                                         printk(KERN_WARNING "detected "
    1021                 :            :                                                 "fb_set_par error, "
    1022                 :            :                                                 "error code: %d\n", ret);
    1023                 :          0 :                                         goto done;
    1024                 :            :                                 }
    1025                 :            :                         }
    1026                 :            : 
    1027                 :          0 :                         fb_pan_display(info, &info->var);
    1028                 :          0 :                         fb_set_cmap(&info->cmap, info);
    1029                 :          0 :                         fb_var_to_videomode(&mode, &info->var);
    1030                 :            : 
    1031 [ #  # ][ #  # ]:          0 :                         if (info->modelist.prev && info->modelist.next &&
                 [ #  # ]
    1032                 :          0 :                             !list_empty(&info->modelist))
    1033                 :          0 :                                 ret = fb_add_videomode(&mode, &info->modelist);
    1034                 :            : 
    1035 [ #  # ][ #  # ]:          0 :                         if (!ret && (flags & FBINFO_MISC_USEREVENT)) {
    1036                 :            :                                 struct fb_event event;
    1037                 :          0 :                                 int evnt = (activate & FB_ACTIVATE_ALL) ?
    1038         [ #  # ]:          0 :                                         FB_EVENT_MODE_CHANGE_ALL :
    1039                 :            :                                         FB_EVENT_MODE_CHANGE;
    1040                 :            : 
    1041                 :          0 :                                 info->flags &= ~FBINFO_MISC_USEREVENT;
    1042                 :          0 :                                 event.info = info;
    1043                 :          0 :                                 event.data = &mode;
    1044                 :          0 :                                 fb_notifier_call_chain(evnt, &event);
    1045                 :            :                         }
    1046                 :            :                 }
    1047                 :            :         }
    1048                 :            : 
    1049                 :            :  done:
    1050                 :          0 :         return ret;
    1051                 :            : }
    1052                 :            : EXPORT_SYMBOL(fb_set_var);
    1053                 :            : 
    1054                 :            : int
    1055                 :          0 : fb_blank(struct fb_info *info, int blank)
    1056                 :            : {       
    1057                 :            :         struct fb_event event;
    1058                 :            :         int ret = -EINVAL, early_ret;
    1059                 :            : 
    1060         [ #  # ]:          0 :         if (blank > FB_BLANK_POWERDOWN)
    1061                 :          0 :                 blank = FB_BLANK_POWERDOWN;
    1062                 :            : 
    1063                 :          0 :         event.info = info;
    1064                 :          0 :         event.data = &blank;
    1065                 :            : 
    1066                 :          0 :         early_ret = fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event);
    1067                 :            : 
    1068         [ #  # ]:          0 :         if (info->fbops->fb_blank)
    1069                 :          0 :                 ret = info->fbops->fb_blank(blank, info);
    1070                 :            : 
    1071         [ #  # ]:          0 :         if (!ret)
    1072                 :          0 :                 fb_notifier_call_chain(FB_EVENT_BLANK, &event);
    1073                 :            :         else {
    1074                 :            :                 /*
    1075                 :            :                  * if fb_blank is failed then revert effects of
    1076                 :            :                  * the early blank event.
    1077                 :            :                  */
    1078         [ #  # ]:          0 :                 if (!early_ret)
    1079                 :          0 :                         fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK, &event);
    1080                 :            :         }
    1081                 :            : 
    1082                 :          0 :         return ret;
    1083                 :            : }
    1084                 :            : EXPORT_SYMBOL(fb_blank);
    1085                 :            : 
    1086                 :          0 : static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
    1087                 :            :                         unsigned long arg)
    1088                 :            : {
    1089                 :            :         struct fb_ops *fb;
    1090                 :            :         struct fb_var_screeninfo var;
    1091                 :            :         struct fb_fix_screeninfo fix;
    1092                 :            :         struct fb_con2fbmap con2fb;
    1093                 :            :         struct fb_cmap cmap_from;
    1094                 :            :         struct fb_cmap_user cmap;
    1095                 :            :         struct fb_event event;
    1096                 :          0 :         void __user *argp = (void __user *)arg;
    1097                 :            :         long ret = 0;
    1098                 :            : 
    1099   [ #  #  #  #  :          0 :         switch (cmd) {
          #  #  #  #  #  
                   #  # ]
    1100                 :            :         case FBIOGET_VSCREENINFO:
    1101         [ #  # ]:          0 :                 if (!lock_fb_info(info))
    1102                 :            :                         return -ENODEV;
    1103                 :          0 :                 var = info->var;
    1104                 :            :                 unlock_fb_info(info);
    1105                 :            : 
    1106         [ #  # ]:          0 :                 ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0;
    1107                 :          0 :                 break;
    1108                 :            :         case FBIOPUT_VSCREENINFO:
    1109         [ #  # ]:          0 :                 if (copy_from_user(&var, argp, sizeof(var)))
    1110                 :            :                         return -EFAULT;
    1111                 :          0 :                 console_lock();
    1112         [ #  # ]:          0 :                 if (!lock_fb_info(info)) {
    1113                 :          0 :                         console_unlock();
    1114                 :          0 :                         return -ENODEV;
    1115                 :            :                 }
    1116                 :          0 :                 info->flags |= FBINFO_MISC_USEREVENT;
    1117                 :          0 :                 ret = fb_set_var(info, &var);
    1118                 :          0 :                 info->flags &= ~FBINFO_MISC_USEREVENT;
    1119                 :            :                 unlock_fb_info(info);
    1120                 :          0 :                 console_unlock();
    1121 [ #  # ][ #  # ]:          0 :                 if (!ret && copy_to_user(argp, &var, sizeof(var)))
    1122                 :            :                         ret = -EFAULT;
    1123                 :            :                 break;
    1124                 :            :         case FBIOGET_FSCREENINFO:
    1125         [ #  # ]:          0 :                 if (!lock_fb_info(info))
    1126                 :            :                         return -ENODEV;
    1127                 :          0 :                 fix = info->fix;
    1128                 :            :                 unlock_fb_info(info);
    1129                 :            : 
    1130         [ #  # ]:          0 :                 ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
    1131                 :          0 :                 break;
    1132                 :            :         case FBIOPUTCMAP:
    1133         [ #  # ]:          0 :                 if (copy_from_user(&cmap, argp, sizeof(cmap)))
    1134                 :            :                         return -EFAULT;
    1135                 :          0 :                 ret = fb_set_user_cmap(&cmap, info);
    1136                 :          0 :                 break;
    1137                 :            :         case FBIOGETCMAP:
    1138         [ #  # ]:          0 :                 if (copy_from_user(&cmap, argp, sizeof(cmap)))
    1139                 :            :                         return -EFAULT;
    1140         [ #  # ]:          0 :                 if (!lock_fb_info(info))
    1141                 :            :                         return -ENODEV;
    1142                 :          0 :                 cmap_from = info->cmap;
    1143                 :            :                 unlock_fb_info(info);
    1144                 :          0 :                 ret = fb_cmap_to_user(&cmap_from, &cmap);
    1145                 :          0 :                 break;
    1146                 :            :         case FBIOPAN_DISPLAY:
    1147         [ #  # ]:          0 :                 if (copy_from_user(&var, argp, sizeof(var)))
    1148                 :            :                         return -EFAULT;
    1149                 :          0 :                 console_lock();
    1150         [ #  # ]:          0 :                 if (!lock_fb_info(info)) {
    1151                 :          0 :                         console_unlock();
    1152                 :          0 :                         return -ENODEV;
    1153                 :            :                 }
    1154                 :          0 :                 ret = fb_pan_display(info, &var);
    1155                 :            :                 unlock_fb_info(info);
    1156                 :          0 :                 console_unlock();
    1157 [ #  # ][ #  # ]:          0 :                 if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
    1158                 :            :                         return -EFAULT;
    1159                 :            :                 break;
    1160                 :            :         case FBIO_CURSOR:
    1161                 :            :                 ret = -EINVAL;
    1162                 :            :                 break;
    1163                 :            :         case FBIOGET_CON2FBMAP:
    1164         [ #  # ]:          0 :                 if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
    1165                 :            :                         return -EFAULT;
    1166         [ #  # ]:          0 :                 if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
    1167                 :            :                         return -EINVAL;
    1168                 :          0 :                 con2fb.framebuffer = -1;
    1169                 :          0 :                 event.data = &con2fb;
    1170         [ #  # ]:          0 :                 if (!lock_fb_info(info))
    1171                 :            :                         return -ENODEV;
    1172                 :          0 :                 event.info = info;
    1173                 :          0 :                 fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
    1174                 :            :                 unlock_fb_info(info);
    1175         [ #  # ]:          0 :                 ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;
    1176                 :          0 :                 break;
    1177                 :            :         case FBIOPUT_CON2FBMAP:
    1178         [ #  # ]:          0 :                 if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
    1179                 :            :                         return -EFAULT;
    1180         [ #  # ]:          0 :                 if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
    1181                 :            :                         return -EINVAL;
    1182         [ #  # ]:          0 :                 if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
    1183                 :            :                         return -EINVAL;
    1184         [ #  # ]:          0 :                 if (!registered_fb[con2fb.framebuffer])
    1185                 :          0 :                         request_module("fb%d", con2fb.framebuffer);
    1186         [ #  # ]:          0 :                 if (!registered_fb[con2fb.framebuffer]) {
    1187                 :            :                         ret = -EINVAL;
    1188                 :            :                         break;
    1189                 :            :                 }
    1190                 :          0 :                 event.data = &con2fb;
    1191                 :          0 :                 console_lock();
    1192         [ #  # ]:          0 :                 if (!lock_fb_info(info)) {
    1193                 :          0 :                         console_unlock();
    1194                 :          0 :                         return -ENODEV;
    1195                 :            :                 }
    1196                 :          0 :                 event.info = info;
    1197                 :          0 :                 ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event);
    1198                 :            :                 unlock_fb_info(info);
    1199                 :          0 :                 console_unlock();
    1200                 :          0 :                 break;
    1201                 :            :         case FBIOBLANK:
    1202                 :          0 :                 console_lock();
    1203         [ #  # ]:          0 :                 if (!lock_fb_info(info)) {
    1204                 :          0 :                         console_unlock();
    1205                 :          0 :                         return -ENODEV;
    1206                 :            :                 }
    1207                 :          0 :                 info->flags |= FBINFO_MISC_USEREVENT;
    1208                 :          0 :                 ret = fb_blank(info, arg);
    1209                 :          0 :                 info->flags &= ~FBINFO_MISC_USEREVENT;
    1210                 :            :                 unlock_fb_info(info);
    1211                 :          0 :                 console_unlock();
    1212                 :          0 :                 break;
    1213                 :            :         default:
    1214         [ #  # ]:          0 :                 if (!lock_fb_info(info))
    1215                 :            :                         return -ENODEV;
    1216                 :          0 :                 fb = info->fbops;
    1217         [ #  # ]:          0 :                 if (fb->fb_ioctl)
    1218                 :          0 :                         ret = fb->fb_ioctl(info, cmd, arg);
    1219                 :            :                 else
    1220                 :            :                         ret = -ENOTTY;
    1221                 :            :                 unlock_fb_info(info);
    1222                 :            :         }
    1223                 :          0 :         return ret;
    1224                 :            : }
    1225                 :            : 
    1226                 :          0 : static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    1227                 :            : {
    1228                 :            :         struct fb_info *info = file_fb_info(file);
    1229                 :            : 
    1230         [ #  # ]:          0 :         if (!info)
    1231                 :            :                 return -ENODEV;
    1232                 :          0 :         return do_fb_ioctl(info, cmd, arg);
    1233                 :            : }
    1234                 :            : 
    1235                 :            : #ifdef CONFIG_COMPAT
    1236                 :            : struct fb_fix_screeninfo32 {
    1237                 :            :         char                    id[16];
    1238                 :            :         compat_caddr_t          smem_start;
    1239                 :            :         u32                     smem_len;
    1240                 :            :         u32                     type;
    1241                 :            :         u32                     type_aux;
    1242                 :            :         u32                     visual;
    1243                 :            :         u16                     xpanstep;
    1244                 :            :         u16                     ypanstep;
    1245                 :            :         u16                     ywrapstep;
    1246                 :            :         u32                     line_length;
    1247                 :            :         compat_caddr_t          mmio_start;
    1248                 :            :         u32                     mmio_len;
    1249                 :            :         u32                     accel;
    1250                 :            :         u16                     reserved[3];
    1251                 :            : };
    1252                 :            : 
    1253                 :            : struct fb_cmap32 {
    1254                 :            :         u32                     start;
    1255                 :            :         u32                     len;
    1256                 :            :         compat_caddr_t  red;
    1257                 :            :         compat_caddr_t  green;
    1258                 :            :         compat_caddr_t  blue;
    1259                 :            :         compat_caddr_t  transp;
    1260                 :            : };
    1261                 :            : 
    1262                 :            : static int fb_getput_cmap(struct fb_info *info, unsigned int cmd,
    1263                 :            :                           unsigned long arg)
    1264                 :            : {
    1265                 :            :         struct fb_cmap_user __user *cmap;
    1266                 :            :         struct fb_cmap32 __user *cmap32;
    1267                 :            :         __u32 data;
    1268                 :            :         int err;
    1269                 :            : 
    1270                 :            :         cmap = compat_alloc_user_space(sizeof(*cmap));
    1271                 :            :         cmap32 = compat_ptr(arg);
    1272                 :            : 
    1273                 :            :         if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32)))
    1274                 :            :                 return -EFAULT;
    1275                 :            : 
    1276                 :            :         if (get_user(data, &cmap32->red) ||
    1277                 :            :             put_user(compat_ptr(data), &cmap->red) ||
    1278                 :            :             get_user(data, &cmap32->green) ||
    1279                 :            :             put_user(compat_ptr(data), &cmap->green) ||
    1280                 :            :             get_user(data, &cmap32->blue) ||
    1281                 :            :             put_user(compat_ptr(data), &cmap->blue) ||
    1282                 :            :             get_user(data, &cmap32->transp) ||
    1283                 :            :             put_user(compat_ptr(data), &cmap->transp))
    1284                 :            :                 return -EFAULT;
    1285                 :            : 
    1286                 :            :         err = do_fb_ioctl(info, cmd, (unsigned long) cmap);
    1287                 :            : 
    1288                 :            :         if (!err) {
    1289                 :            :                 if (copy_in_user(&cmap32->start,
    1290                 :            :                                  &cmap->start,
    1291                 :            :                                  2 * sizeof(__u32)))
    1292                 :            :                         err = -EFAULT;
    1293                 :            :         }
    1294                 :            :         return err;
    1295                 :            : }
    1296                 :            : 
    1297                 :            : static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix,
    1298                 :            :                                   struct fb_fix_screeninfo32 __user *fix32)
    1299                 :            : {
    1300                 :            :         __u32 data;
    1301                 :            :         int err;
    1302                 :            : 
    1303                 :            :         err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id));
    1304                 :            : 
    1305                 :            :         data = (__u32) (unsigned long) fix->smem_start;
    1306                 :            :         err |= put_user(data, &fix32->smem_start);
    1307                 :            : 
    1308                 :            :         err |= put_user(fix->smem_len, &fix32->smem_len);
    1309                 :            :         err |= put_user(fix->type, &fix32->type);
    1310                 :            :         err |= put_user(fix->type_aux, &fix32->type_aux);
    1311                 :            :         err |= put_user(fix->visual, &fix32->visual);
    1312                 :            :         err |= put_user(fix->xpanstep, &fix32->xpanstep);
    1313                 :            :         err |= put_user(fix->ypanstep, &fix32->ypanstep);
    1314                 :            :         err |= put_user(fix->ywrapstep, &fix32->ywrapstep);
    1315                 :            :         err |= put_user(fix->line_length, &fix32->line_length);
    1316                 :            : 
    1317                 :            :         data = (__u32) (unsigned long) fix->mmio_start;
    1318                 :            :         err |= put_user(data, &fix32->mmio_start);
    1319                 :            : 
    1320                 :            :         err |= put_user(fix->mmio_len, &fix32->mmio_len);
    1321                 :            :         err |= put_user(fix->accel, &fix32->accel);
    1322                 :            :         err |= copy_to_user(fix32->reserved, fix->reserved,
    1323                 :            :                             sizeof(fix->reserved));
    1324                 :            : 
    1325                 :            :         if (err)
    1326                 :            :                 return -EFAULT;
    1327                 :            :         return 0;
    1328                 :            : }
    1329                 :            : 
    1330                 :            : static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
    1331                 :            :                               unsigned long arg)
    1332                 :            : {
    1333                 :            :         mm_segment_t old_fs;
    1334                 :            :         struct fb_fix_screeninfo fix;
    1335                 :            :         struct fb_fix_screeninfo32 __user *fix32;
    1336                 :            :         int err;
    1337                 :            : 
    1338                 :            :         fix32 = compat_ptr(arg);
    1339                 :            : 
    1340                 :            :         old_fs = get_fs();
    1341                 :            :         set_fs(KERNEL_DS);
    1342                 :            :         err = do_fb_ioctl(info, cmd, (unsigned long) &fix);
    1343                 :            :         set_fs(old_fs);
    1344                 :            : 
    1345                 :            :         if (!err)
    1346                 :            :                 err = do_fscreeninfo_to_user(&fix, fix32);
    1347                 :            : 
    1348                 :            :         return err;
    1349                 :            : }
    1350                 :            : 
    1351                 :            : static long fb_compat_ioctl(struct file *file, unsigned int cmd,
    1352                 :            :                             unsigned long arg)
    1353                 :            : {
    1354                 :            :         struct fb_info *info = file_fb_info(file);
    1355                 :            :         struct fb_ops *fb;
    1356                 :            :         long ret = -ENOIOCTLCMD;
    1357                 :            : 
    1358                 :            :         if (!info)
    1359                 :            :                 return -ENODEV;
    1360                 :            :         fb = info->fbops;
    1361                 :            :         switch(cmd) {
    1362                 :            :         case FBIOGET_VSCREENINFO:
    1363                 :            :         case FBIOPUT_VSCREENINFO:
    1364                 :            :         case FBIOPAN_DISPLAY:
    1365                 :            :         case FBIOGET_CON2FBMAP:
    1366                 :            :         case FBIOPUT_CON2FBMAP:
    1367                 :            :                 arg = (unsigned long) compat_ptr(arg);
    1368                 :            :         case FBIOBLANK:
    1369                 :            :                 ret = do_fb_ioctl(info, cmd, arg);
    1370                 :            :                 break;
    1371                 :            : 
    1372                 :            :         case FBIOGET_FSCREENINFO:
    1373                 :            :                 ret = fb_get_fscreeninfo(info, cmd, arg);
    1374                 :            :                 break;
    1375                 :            : 
    1376                 :            :         case FBIOGETCMAP:
    1377                 :            :         case FBIOPUTCMAP:
    1378                 :            :                 ret = fb_getput_cmap(info, cmd, arg);
    1379                 :            :                 break;
    1380                 :            : 
    1381                 :            :         default:
    1382                 :            :                 if (fb->fb_compat_ioctl)
    1383                 :            :                         ret = fb->fb_compat_ioctl(info, cmd, arg);
    1384                 :            :                 break;
    1385                 :            :         }
    1386                 :            :         return ret;
    1387                 :            : }
    1388                 :            : #endif
    1389                 :            : 
    1390                 :            : static int
    1391                 :          0 : fb_mmap(struct file *file, struct vm_area_struct * vma)
    1392                 :            : {
    1393                 :            :         struct fb_info *info = file_fb_info(file);
    1394                 :            :         struct fb_ops *fb;
    1395                 :            :         unsigned long mmio_pgoff;
    1396                 :            :         unsigned long start;
    1397                 :            :         u32 len;
    1398                 :            : 
    1399         [ #  # ]:          0 :         if (!info)
    1400                 :            :                 return -ENODEV;
    1401                 :          0 :         fb = info->fbops;
    1402         [ #  # ]:          0 :         if (!fb)
    1403                 :            :                 return -ENODEV;
    1404                 :          0 :         mutex_lock(&info->mm_lock);
    1405         [ #  # ]:          0 :         if (fb->fb_mmap) {
    1406                 :            :                 int res;
    1407                 :          0 :                 res = fb->fb_mmap(info, vma);
    1408                 :          0 :                 mutex_unlock(&info->mm_lock);
    1409                 :          0 :                 return res;
    1410                 :            :         }
    1411                 :            : 
    1412                 :            :         /*
    1413                 :            :          * Ugh. This can be either the frame buffer mapping, or
    1414                 :            :          * if pgoff points past it, the mmio mapping.
    1415                 :            :          */
    1416                 :          0 :         start = info->fix.smem_start;
    1417                 :          0 :         len = info->fix.smem_len;
    1418                 :          0 :         mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
    1419         [ #  # ]:          0 :         if (vma->vm_pgoff >= mmio_pgoff) {
    1420         [ #  # ]:          0 :                 if (info->var.accel_flags) {
    1421                 :          0 :                         mutex_unlock(&info->mm_lock);
    1422                 :          0 :                         return -EINVAL;
    1423                 :            :                 }
    1424                 :            : 
    1425                 :          0 :                 vma->vm_pgoff -= mmio_pgoff;
    1426                 :          0 :                 start = info->fix.mmio_start;
    1427                 :          0 :                 len = info->fix.mmio_len;
    1428                 :            :         }
    1429                 :          0 :         mutex_unlock(&info->mm_lock);
    1430                 :            : 
    1431                 :          0 :         vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
    1432                 :            :         fb_pgprotect(file, vma, start);
    1433                 :            : 
    1434                 :          0 :         return vm_iomap_memory(vma, start, len);
    1435                 :            : }
    1436                 :            : 
    1437                 :            : static int
    1438                 :          0 : fb_open(struct inode *inode, struct file *file)
    1439                 :            : __acquires(&info->lock)
    1440                 :            : __releases(&info->lock)
    1441                 :            : {
    1442                 :          0 :         int fbidx = iminor(inode);
    1443                 :            :         struct fb_info *info;
    1444                 :            :         int res = 0;
    1445                 :            : 
    1446                 :          0 :         info = get_fb_info(fbidx);
    1447         [ #  # ]:          0 :         if (!info) {
    1448                 :          0 :                 request_module("fb%d", fbidx);
    1449                 :          0 :                 info = get_fb_info(fbidx);
    1450         [ #  # ]:          0 :                 if (!info)
    1451                 :            :                         return -ENODEV;
    1452                 :            :         }
    1453         [ #  # ]:          0 :         if (IS_ERR(info))
    1454                 :          0 :                 return PTR_ERR(info);
    1455                 :            : 
    1456                 :          0 :         mutex_lock(&info->lock);
    1457         [ #  # ]:          0 :         if (!try_module_get(info->fbops->owner)) {
    1458                 :            :                 res = -ENODEV;
    1459                 :            :                 goto out;
    1460                 :            :         }
    1461                 :          0 :         file->private_data = info;
    1462         [ #  # ]:          0 :         if (info->fbops->fb_open) {
    1463                 :          0 :                 res = info->fbops->fb_open(info,1);
    1464         [ #  # ]:          0 :                 if (res)
    1465                 :          0 :                         module_put(info->fbops->owner);
    1466                 :            :         }
    1467                 :            : #ifdef CONFIG_FB_DEFERRED_IO
    1468                 :            :         if (info->fbdefio)
    1469                 :            :                 fb_deferred_io_open(info, inode, file);
    1470                 :            : #endif
    1471                 :            : out:
    1472                 :          0 :         mutex_unlock(&info->lock);
    1473         [ #  # ]:          0 :         if (res)
    1474                 :          0 :                 put_fb_info(info);
    1475                 :          0 :         return res;
    1476                 :            : }
    1477                 :            : 
    1478                 :            : static int 
    1479                 :          0 : fb_release(struct inode *inode, struct file *file)
    1480                 :            : __acquires(&info->lock)
    1481                 :            : __releases(&info->lock)
    1482                 :            : {
    1483                 :          0 :         struct fb_info * const info = file->private_data;
    1484                 :            : 
    1485                 :          0 :         mutex_lock(&info->lock);
    1486         [ #  # ]:          0 :         if (info->fbops->fb_release)
    1487                 :          0 :                 info->fbops->fb_release(info,1);
    1488                 :          0 :         module_put(info->fbops->owner);
    1489                 :          0 :         mutex_unlock(&info->lock);
    1490                 :          0 :         put_fb_info(info);
    1491                 :          0 :         return 0;
    1492                 :            : }
    1493                 :            : 
    1494                 :            : static const struct file_operations fb_fops = {
    1495                 :            :         .owner =        THIS_MODULE,
    1496                 :            :         .read =         fb_read,
    1497                 :            :         .write =        fb_write,
    1498                 :            :         .unlocked_ioctl = fb_ioctl,
    1499                 :            : #ifdef CONFIG_COMPAT
    1500                 :            :         .compat_ioctl = fb_compat_ioctl,
    1501                 :            : #endif
    1502                 :            :         .mmap =         fb_mmap,
    1503                 :            :         .open =         fb_open,
    1504                 :            :         .release =      fb_release,
    1505                 :            : #ifdef HAVE_ARCH_FB_UNMAPPED_AREA
    1506                 :            :         .get_unmapped_area = get_fb_unmapped_area,
    1507                 :            : #endif
    1508                 :            : #ifdef CONFIG_FB_DEFERRED_IO
    1509                 :            :         .fsync =        fb_deferred_io_fsync,
    1510                 :            : #endif
    1511                 :            :         .llseek =       default_llseek,
    1512                 :            : };
    1513                 :            : 
    1514                 :            : struct class *fb_class;
    1515                 :            : EXPORT_SYMBOL(fb_class);
    1516                 :            : 
    1517                 :          0 : static int fb_check_foreignness(struct fb_info *fi)
    1518                 :            : {
    1519                 :          0 :         const bool foreign_endian = fi->flags & FBINFO_FOREIGN_ENDIAN;
    1520                 :            : 
    1521                 :          0 :         fi->flags &= ~FBINFO_FOREIGN_ENDIAN;
    1522                 :            : 
    1523                 :            : #ifdef __BIG_ENDIAN
    1524                 :            :         fi->flags |= foreign_endian ? 0 : FBINFO_BE_MATH;
    1525                 :            : #else
    1526         [ #  # ]:          0 :         fi->flags |= foreign_endian ? FBINFO_BE_MATH : 0;
    1527                 :            : #endif /* __BIG_ENDIAN */
    1528                 :            : 
    1529         [ #  # ]:          0 :         if (fi->flags & FBINFO_BE_MATH && !fb_be_math(fi)) {
    1530                 :          0 :                 pr_err("%s: enable CONFIG_FB_BIG_ENDIAN to "
    1531                 :            :                        "support this framebuffer\n", fi->fix.id);
    1532                 :          0 :                 return -ENOSYS;
    1533                 :            :         } else if (!(fi->flags & FBINFO_BE_MATH) && fb_be_math(fi)) {
    1534                 :            :                 pr_err("%s: enable CONFIG_FB_LITTLE_ENDIAN to "
    1535                 :            :                        "support this framebuffer\n", fi->fix.id);
    1536                 :            :                 return -ENOSYS;
    1537                 :            :         }
    1538                 :            : 
    1539                 :            :         return 0;
    1540                 :            : }
    1541                 :            : 
    1542                 :            : static bool apertures_overlap(struct aperture *gen, struct aperture *hw)
    1543                 :            : {
    1544                 :            :         /* is the generic aperture base the same as the HW one */
    1545         [ #  # ]:          0 :         if (gen->base == hw->base)
    1546                 :            :                 return true;
    1547                 :            :         /* is the generic aperture base inside the hw base->hw base+size */
    1548 [ #  # ][ #  # ]:          0 :         if (gen->base > hw->base && gen->base < hw->base + hw->size)
    1549                 :            :                 return true;
    1550                 :            :         return false;
    1551                 :            : }
    1552                 :            : 
    1553                 :          0 : static bool fb_do_apertures_overlap(struct apertures_struct *gena,
    1554                 :            :                                     struct apertures_struct *hwa)
    1555                 :            : {
    1556                 :            :         int i, j;
    1557         [ #  # ]:          0 :         if (!hwa || !gena)
    1558                 :            :                 return false;
    1559                 :            : 
    1560         [ #  # ]:          0 :         for (i = 0; i < hwa->count; ++i) {
    1561                 :          0 :                 struct aperture *h = &hwa->ranges[i];
    1562         [ #  # ]:          0 :                 for (j = 0; j < gena->count; ++j) {
    1563                 :          0 :                         struct aperture *g = &gena->ranges[j];
    1564                 :          0 :                         printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n",
    1565                 :          0 :                                 (unsigned long long)g->base,
    1566                 :          0 :                                 (unsigned long long)g->size,
    1567                 :          0 :                                 (unsigned long long)h->base,
    1568                 :          0 :                                 (unsigned long long)h->size);
    1569         [ #  # ]:          0 :                         if (apertures_overlap(g, h))
    1570                 :            :                                 return true;
    1571                 :            :                 }
    1572                 :            :         }
    1573                 :            : 
    1574                 :            :         return false;
    1575                 :            : }
    1576                 :            : 
    1577                 :            : static int do_unregister_framebuffer(struct fb_info *fb_info);
    1578                 :            : 
    1579                 :            : #define VGA_FB_PHYS 0xA0000
    1580                 :          0 : static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
    1581                 :            :                                      const char *name, bool primary)
    1582                 :            : {
    1583                 :            :         int i;
    1584                 :            : 
    1585                 :            :         /* check all firmware fbs and kick off if the base addr overlaps */
    1586         [ #  # ]:          0 :         for (i = 0 ; i < FB_MAX; i++) {
    1587                 :            :                 struct apertures_struct *gen_aper;
    1588         [ #  # ]:          0 :                 if (!registered_fb[i])
    1589                 :          0 :                         continue;
    1590                 :            : 
    1591         [ #  # ]:          0 :                 if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
    1592                 :          0 :                         continue;
    1593                 :            : 
    1594                 :          0 :                 gen_aper = registered_fb[i]->apertures;
    1595 [ #  # ][ #  # ]:          0 :                 if (fb_do_apertures_overlap(gen_aper, a) ||
    1596 [ #  # ][ #  # ]:          0 :                         (primary && gen_aper && gen_aper->count &&
    1597                 :          0 :                          gen_aper->ranges[0].base == VGA_FB_PHYS)) {
    1598                 :            : 
    1599                 :          0 :                         printk(KERN_INFO "fb: conflicting fb hw usage "
    1600                 :            :                                "%s vs %s - removing generic driver\n",
    1601                 :          0 :                                name, registered_fb[i]->fix.id);
    1602                 :          0 :                         do_unregister_framebuffer(registered_fb[i]);
    1603                 :            :                 }
    1604                 :            :         }
    1605                 :          0 : }
    1606                 :            : 
    1607                 :          0 : static int do_register_framebuffer(struct fb_info *fb_info)
    1608                 :            : {
    1609                 :            :         int i;
    1610                 :            :         struct fb_event event;
    1611                 :            :         struct fb_videomode mode;
    1612                 :            : 
    1613         [ #  # ]:          0 :         if (fb_check_foreignness(fb_info))
    1614                 :            :                 return -ENOSYS;
    1615                 :            : 
    1616                 :          0 :         do_remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
    1617                 :            :                                          fb_is_primary_device(fb_info));
    1618                 :            : 
    1619         [ #  # ]:          0 :         if (num_registered_fb == FB_MAX)
    1620                 :            :                 return -ENXIO;
    1621                 :            : 
    1622                 :          0 :         num_registered_fb++;
    1623         [ #  # ]:          0 :         for (i = 0 ; i < FB_MAX; i++)
    1624         [ #  # ]:          0 :                 if (!registered_fb[i])
    1625                 :            :                         break;
    1626                 :          0 :         fb_info->node = i;
    1627                 :          0 :         atomic_set(&fb_info->count, 1);
    1628                 :          0 :         mutex_init(&fb_info->lock);
    1629                 :          0 :         mutex_init(&fb_info->mm_lock);
    1630                 :            : 
    1631                 :          0 :         fb_info->dev = device_create(fb_class, fb_info->device,
    1632                 :          0 :                                      MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
    1633         [ #  # ]:          0 :         if (IS_ERR(fb_info->dev)) {
    1634                 :            :                 /* Not fatal */
    1635                 :          0 :                 printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
    1636                 :          0 :                 fb_info->dev = NULL;
    1637                 :            :         } else
    1638                 :          0 :                 fb_init_device(fb_info);
    1639                 :            : 
    1640         [ #  # ]:          0 :         if (fb_info->pixmap.addr == NULL) {
    1641                 :          0 :                 fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
    1642         [ #  # ]:          0 :                 if (fb_info->pixmap.addr) {
    1643                 :          0 :                         fb_info->pixmap.size = FBPIXMAPSIZE;
    1644                 :          0 :                         fb_info->pixmap.buf_align = 1;
    1645                 :          0 :                         fb_info->pixmap.scan_align = 1;
    1646                 :          0 :                         fb_info->pixmap.access_align = 32;
    1647                 :          0 :                         fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
    1648                 :            :                 }
    1649                 :            :         }       
    1650                 :          0 :         fb_info->pixmap.offset = 0;
    1651                 :            : 
    1652         [ #  # ]:          0 :         if (!fb_info->pixmap.blit_x)
    1653                 :          0 :                 fb_info->pixmap.blit_x = ~(u32)0;
    1654                 :            : 
    1655         [ #  # ]:          0 :         if (!fb_info->pixmap.blit_y)
    1656                 :          0 :                 fb_info->pixmap.blit_y = ~(u32)0;
    1657                 :            : 
    1658 [ #  # ][ #  # ]:          0 :         if (!fb_info->modelist.prev || !fb_info->modelist.next)
    1659                 :          0 :                 INIT_LIST_HEAD(&fb_info->modelist);
    1660                 :            : 
    1661         [ #  # ]:          0 :         if (fb_info->skip_vt_switch)
    1662                 :          0 :                 pm_vt_switch_required(fb_info->dev, false);
    1663                 :            :         else
    1664                 :          0 :                 pm_vt_switch_required(fb_info->dev, true);
    1665                 :            : 
    1666                 :          0 :         fb_var_to_videomode(&mode, &fb_info->var);
    1667                 :          0 :         fb_add_videomode(&mode, &fb_info->modelist);
    1668                 :          0 :         registered_fb[i] = fb_info;
    1669                 :            : 
    1670                 :          0 :         event.info = fb_info;
    1671                 :          0 :         console_lock();
    1672         [ #  # ]:          0 :         if (!lock_fb_info(fb_info)) {
    1673                 :          0 :                 console_unlock();
    1674                 :          0 :                 return -ENODEV;
    1675                 :            :         }
    1676                 :            : 
    1677                 :          0 :         fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
    1678                 :            :         unlock_fb_info(fb_info);
    1679                 :          0 :         console_unlock();
    1680                 :          0 :         return 0;
    1681                 :            : }
    1682                 :            : 
    1683                 :          0 : static int do_unregister_framebuffer(struct fb_info *fb_info)
    1684                 :            : {
    1685                 :            :         struct fb_event event;
    1686                 :            :         int i, ret = 0;
    1687                 :            : 
    1688                 :          0 :         i = fb_info->node;
    1689 [ #  # ][ #  # ]:          0 :         if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
    1690                 :            :                 return -EINVAL;
    1691                 :            : 
    1692                 :          0 :         console_lock();
    1693         [ #  # ]:          0 :         if (!lock_fb_info(fb_info)) {
    1694                 :          0 :                 console_unlock();
    1695                 :          0 :                 return -ENODEV;
    1696                 :            :         }
    1697                 :            : 
    1698                 :          0 :         event.info = fb_info;
    1699                 :          0 :         ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
    1700                 :            :         unlock_fb_info(fb_info);
    1701                 :          0 :         console_unlock();
    1702                 :            : 
    1703         [ #  # ]:          0 :         if (ret)
    1704                 :            :                 return -EINVAL;
    1705                 :            : 
    1706                 :          0 :         pm_vt_switch_unregister(fb_info->dev);
    1707                 :            : 
    1708                 :          0 :         unlink_framebuffer(fb_info);
    1709 [ #  # ][ #  # ]:          0 :         if (fb_info->pixmap.addr &&
    1710                 :          0 :             (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
    1711                 :          0 :                 kfree(fb_info->pixmap.addr);
    1712                 :          0 :         fb_destroy_modelist(&fb_info->modelist);
    1713                 :          0 :         registered_fb[i] = NULL;
    1714                 :          0 :         num_registered_fb--;
    1715                 :          0 :         fb_cleanup_device(fb_info);
    1716                 :          0 :         event.info = fb_info;
    1717                 :          0 :         console_lock();
    1718                 :          0 :         fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
    1719                 :          0 :         console_unlock();
    1720                 :            : 
    1721                 :            :         /* this may free fb info */
    1722                 :          0 :         put_fb_info(fb_info);
    1723                 :          0 :         return 0;
    1724                 :            : }
    1725                 :            : 
    1726                 :          0 : int unlink_framebuffer(struct fb_info *fb_info)
    1727                 :            : {
    1728                 :            :         int i;
    1729                 :            : 
    1730                 :          0 :         i = fb_info->node;
    1731 [ #  # ][ #  # ]:          0 :         if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
    1732                 :            :                 return -EINVAL;
    1733                 :            : 
    1734         [ #  # ]:          0 :         if (fb_info->dev) {
    1735                 :          0 :                 device_destroy(fb_class, MKDEV(FB_MAJOR, i));
    1736                 :          0 :                 fb_info->dev = NULL;
    1737                 :            :         }
    1738                 :            :         return 0;
    1739                 :            : }
    1740                 :            : EXPORT_SYMBOL(unlink_framebuffer);
    1741                 :            : 
    1742                 :          0 : void remove_conflicting_framebuffers(struct apertures_struct *a,
    1743                 :            :                                      const char *name, bool primary)
    1744                 :            : {
    1745                 :          0 :         mutex_lock(&registration_lock);
    1746                 :          0 :         do_remove_conflicting_framebuffers(a, name, primary);
    1747                 :          0 :         mutex_unlock(&registration_lock);
    1748                 :          0 : }
    1749                 :            : EXPORT_SYMBOL(remove_conflicting_framebuffers);
    1750                 :            : 
    1751                 :            : /**
    1752                 :            :  *      register_framebuffer - registers a frame buffer device
    1753                 :            :  *      @fb_info: frame buffer info structure
    1754                 :            :  *
    1755                 :            :  *      Registers a frame buffer device @fb_info.
    1756                 :            :  *
    1757                 :            :  *      Returns negative errno on error, or zero for success.
    1758                 :            :  *
    1759                 :            :  */
    1760                 :            : int
    1761                 :          0 : register_framebuffer(struct fb_info *fb_info)
    1762                 :            : {
    1763                 :            :         int ret;
    1764                 :            : 
    1765                 :          0 :         mutex_lock(&registration_lock);
    1766                 :          0 :         ret = do_register_framebuffer(fb_info);
    1767                 :          0 :         mutex_unlock(&registration_lock);
    1768                 :            : 
    1769                 :          0 :         return ret;
    1770                 :            : }
    1771                 :            : EXPORT_SYMBOL(register_framebuffer);
    1772                 :            : 
    1773                 :            : /**
    1774                 :            :  *      unregister_framebuffer - releases a frame buffer device
    1775                 :            :  *      @fb_info: frame buffer info structure
    1776                 :            :  *
    1777                 :            :  *      Unregisters a frame buffer device @fb_info.
    1778                 :            :  *
    1779                 :            :  *      Returns negative errno on error, or zero for success.
    1780                 :            :  *
    1781                 :            :  *      This function will also notify the framebuffer console
    1782                 :            :  *      to release the driver.
    1783                 :            :  *
    1784                 :            :  *      This is meant to be called within a driver's module_exit()
    1785                 :            :  *      function. If this is called outside module_exit(), ensure
    1786                 :            :  *      that the driver implements fb_open() and fb_release() to
    1787                 :            :  *      check that no processes are using the device.
    1788                 :            :  */
    1789                 :            : int
    1790                 :          0 : unregister_framebuffer(struct fb_info *fb_info)
    1791                 :            : {
    1792                 :            :         int ret;
    1793                 :            : 
    1794                 :          0 :         mutex_lock(&registration_lock);
    1795                 :          0 :         ret = do_unregister_framebuffer(fb_info);
    1796                 :          0 :         mutex_unlock(&registration_lock);
    1797                 :            : 
    1798                 :          0 :         return ret;
    1799                 :            : }
    1800                 :            : EXPORT_SYMBOL(unregister_framebuffer);
    1801                 :            : 
    1802                 :            : /**
    1803                 :            :  *      fb_set_suspend - low level driver signals suspend
    1804                 :            :  *      @info: framebuffer affected
    1805                 :            :  *      @state: 0 = resuming, !=0 = suspending
    1806                 :            :  *
    1807                 :            :  *      This is meant to be used by low level drivers to
    1808                 :            :  *      signal suspend/resume to the core & clients.
    1809                 :            :  *      It must be called with the console semaphore held
    1810                 :            :  */
    1811                 :          0 : void fb_set_suspend(struct fb_info *info, int state)
    1812                 :            : {
    1813                 :            :         struct fb_event event;
    1814                 :            : 
    1815                 :          0 :         event.info = info;
    1816         [ #  # ]:          0 :         if (state) {
    1817                 :          0 :                 fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
    1818                 :          0 :                 info->state = FBINFO_STATE_SUSPENDED;
    1819                 :            :         } else {
    1820                 :          0 :                 info->state = FBINFO_STATE_RUNNING;
    1821                 :          0 :                 fb_notifier_call_chain(FB_EVENT_RESUME, &event);
    1822                 :            :         }
    1823                 :          0 : }
    1824                 :            : EXPORT_SYMBOL(fb_set_suspend);
    1825                 :            : 
    1826                 :            : /**
    1827                 :            :  *      fbmem_init - init frame buffer subsystem
    1828                 :            :  *
    1829                 :            :  *      Initialize the frame buffer subsystem.
    1830                 :            :  *
    1831                 :            :  *      NOTE: This function is _only_ to be called by drivers/char/mem.c.
    1832                 :            :  *
    1833                 :            :  */
    1834                 :            : 
    1835                 :            : static int __init
    1836                 :          0 : fbmem_init(void)
    1837                 :            : {
    1838                 :            :         proc_create("fb", 0, NULL, &fb_proc_fops);
    1839                 :            : 
    1840         [ #  # ]:          0 :         if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
    1841                 :          0 :                 printk("unable to get major %d for fb devs\n", FB_MAJOR);
    1842                 :            : 
    1843                 :          0 :         fb_class = class_create(THIS_MODULE, "graphics");
    1844         [ #  # ]:          0 :         if (IS_ERR(fb_class)) {
    1845                 :          0 :                 printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
    1846                 :          0 :                 fb_class = NULL;
    1847                 :            :         }
    1848                 :          0 :         return 0;
    1849                 :            : }
    1850                 :            : 
    1851                 :            : #ifdef MODULE
    1852                 :            : module_init(fbmem_init);
    1853                 :            : static void __exit
    1854                 :            : fbmem_exit(void)
    1855                 :            : {
    1856                 :            :         remove_proc_entry("fb", NULL);
    1857                 :            :         class_destroy(fb_class);
    1858                 :            :         unregister_chrdev(FB_MAJOR, "fb");
    1859                 :            : }
    1860                 :            : 
    1861                 :            : module_exit(fbmem_exit);
    1862                 :            : MODULE_LICENSE("GPL");
    1863                 :            : MODULE_DESCRIPTION("Framebuffer base");
    1864                 :            : #else
    1865                 :            : subsys_initcall(fbmem_init);
    1866                 :            : #endif
    1867                 :            : 
    1868                 :          0 : int fb_new_modelist(struct fb_info *info)
    1869                 :            : {
    1870                 :            :         struct fb_event event;
    1871                 :          0 :         struct fb_var_screeninfo var = info->var;
    1872                 :            :         struct list_head *pos, *n;
    1873                 :            :         struct fb_modelist *modelist;
    1874                 :            :         struct fb_videomode *m, mode;
    1875                 :            :         int err = 1;
    1876                 :            : 
    1877         [ #  # ]:          0 :         list_for_each_safe(pos, n, &info->modelist) {
    1878                 :            :                 modelist = list_entry(pos, struct fb_modelist, list);
    1879                 :          0 :                 m = &modelist->mode;
    1880                 :          0 :                 fb_videomode_to_var(&var, m);
    1881                 :          0 :                 var.activate = FB_ACTIVATE_TEST;
    1882                 :          0 :                 err = fb_set_var(info, &var);
    1883                 :          0 :                 fb_var_to_videomode(&mode, &var);
    1884 [ #  # ][ #  # ]:          0 :                 if (err || !fb_mode_is_equal(m, &mode)) {
    1885                 :            :                         list_del(pos);
    1886                 :          0 :                         kfree(pos);
    1887                 :            :                 }
    1888                 :            :         }
    1889                 :            : 
    1890                 :            :         err = 1;
    1891                 :            : 
    1892         [ #  # ]:          0 :         if (!list_empty(&info->modelist)) {
    1893                 :          0 :                 event.info = info;
    1894                 :          0 :                 err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
    1895                 :            :         }
    1896                 :            : 
    1897                 :          0 :         return err;
    1898                 :            : }
    1899                 :            : 
    1900                 :            : static char *video_options[FB_MAX] __read_mostly;
    1901                 :            : static int ofonly __read_mostly;
    1902                 :            : 
    1903                 :            : /**
    1904                 :            :  * fb_get_options - get kernel boot parameters
    1905                 :            :  * @name:   framebuffer name as it would appear in
    1906                 :            :  *          the boot parameter line
    1907                 :            :  *          (video=<name>:<options>)
    1908                 :            :  * @option: the option will be stored here
    1909                 :            :  *
    1910                 :            :  * NOTE: Needed to maintain backwards compatibility
    1911                 :            :  */
    1912                 :          0 : int fb_get_options(const char *name, char **option)
    1913                 :            : {
    1914                 :            :         char *opt, *options = NULL;
    1915                 :            :         int retval = 0;
    1916                 :          0 :         int name_len = strlen(name), i;
    1917                 :            : 
    1918 [ #  # ][ #  # ]:          0 :         if (name_len && ofonly && strncmp(name, "offb", 4))
                 [ #  # ]
    1919                 :            :                 retval = 1;
    1920                 :            : 
    1921         [ #  # ]:          0 :         if (name_len && !retval) {
    1922         [ #  # ]:          0 :                 for (i = 0; i < FB_MAX; i++) {
    1923         [ #  # ]:          0 :                         if (video_options[i] == NULL)
    1924                 :          0 :                                 continue;
    1925         [ #  # ]:          0 :                         if (!video_options[i][0])
    1926                 :          0 :                                 continue;
    1927                 :            :                         opt = video_options[i];
    1928 [ #  # ][ #  # ]:          0 :                         if (!strncmp(name, opt, name_len) &&
    1929                 :          0 :                             opt[name_len] == ':')
    1930                 :          0 :                                 options = opt + name_len + 1;
    1931                 :            :                 }
    1932                 :            :         }
    1933 [ #  # ][ #  # ]:          0 :         if (options && !strncmp(options, "off", 3))
    1934                 :            :                 retval = 1;
    1935                 :            : 
    1936         [ #  # ]:          0 :         if (option)
    1937                 :          0 :                 *option = options;
    1938                 :            : 
    1939                 :          0 :         return retval;
    1940                 :            : }
    1941                 :            : EXPORT_SYMBOL(fb_get_options);
    1942                 :            : 
    1943                 :            : #ifndef MODULE
    1944                 :            : /**
    1945                 :            :  *      video_setup - process command line options
    1946                 :            :  *      @options: string of options
    1947                 :            :  *
    1948                 :            :  *      Process command line options for frame buffer subsystem.
    1949                 :            :  *
    1950                 :            :  *      NOTE: This function is a __setup and __init function.
    1951                 :            :  *            It only stores the options.  Drivers have to call
    1952                 :            :  *            fb_get_options() as necessary.
    1953                 :            :  *
    1954                 :            :  *      Returns zero.
    1955                 :            :  *
    1956                 :            :  */
    1957                 :          0 : static int __init video_setup(char *options)
    1958                 :            : {
    1959                 :            :         int i, global = 0;
    1960                 :            : 
    1961 [ #  # ][ #  # ]:          0 :         if (!options || !*options)
    1962                 :            :                 global = 1;
    1963                 :            : 
    1964 [ #  # ][ #  # ]:          0 :         if (!global && !strncmp(options, "ofonly", 6)) {
    1965                 :          0 :                 ofonly = 1;
    1966                 :            :                 global = 1;
    1967                 :            :         }
    1968                 :            : 
    1969 [ #  # ][ #  # ]:          0 :         if (!global && !strchr(options, ':')) {
    1970                 :          0 :                 fb_mode_option = options;
    1971                 :            :                 global = 1;
    1972                 :            :         }
    1973                 :            : 
    1974         [ #  # ]:          0 :         if (!global) {
    1975         [ #  # ]:          0 :                 for (i = 0; i < FB_MAX; i++) {
    1976         [ #  # ]:          0 :                         if (video_options[i] == NULL) {
    1977                 :          0 :                                 video_options[i] = options;
    1978                 :          0 :                                 break;
    1979                 :            :                         }
    1980                 :            : 
    1981                 :            :                 }
    1982                 :            :         }
    1983                 :            : 
    1984                 :          0 :         return 1;
    1985                 :            : }
    1986                 :            : __setup("video=", video_setup);
    1987                 :            : #endif
    1988                 :            : 
    1989                 :            : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.9