root/arch/x86/boot/video-vesa.c

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

DEFINITIONS

This source file includes following definitions.
  1. vesa_store_mode_params_graphics
  2. vesa_probe
  3. vesa_set_mode
  4. vesa_dac_set_8bits
  5. vesa_store_pm_info
  6. vesa_store_mode_params_graphics
  7. vesa_store_edid

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* -*- linux-c -*- ------------------------------------------------------- *
   3  *
   4  *   Copyright (C) 1991, 1992 Linus Torvalds
   5  *   Copyright 2007 rPath, Inc. - All Rights Reserved
   6  *   Copyright 2009 Intel Corporation; author H. Peter Anvin
   7  *
   8  * ----------------------------------------------------------------------- */
   9 
  10 /*
  11  * VESA text modes
  12  */
  13 
  14 #include "boot.h"
  15 #include "video.h"
  16 #include "vesa.h"
  17 #include "string.h"
  18 
  19 /* VESA information */
  20 static struct vesa_general_info vginfo;
  21 static struct vesa_mode_info vminfo;
  22 
  23 static __videocard video_vesa;
  24 
  25 #ifndef _WAKEUP
  26 static void vesa_store_mode_params_graphics(void);
  27 #else /* _WAKEUP */
  28 static inline void vesa_store_mode_params_graphics(void) {}
  29 #endif /* _WAKEUP */
  30 
  31 static int vesa_probe(void)
  32 {
  33         struct biosregs ireg, oreg;
  34         u16 mode;
  35         addr_t mode_ptr;
  36         struct mode_info *mi;
  37         int nmodes = 0;
  38 
  39         video_vesa.modes = GET_HEAP(struct mode_info, 0);
  40 
  41         initregs(&ireg);
  42         ireg.ax = 0x4f00;
  43         ireg.di = (size_t)&vginfo;
  44         intcall(0x10, &ireg, &oreg);
  45 
  46         if (oreg.ax != 0x004f ||
  47             vginfo.signature != VESA_MAGIC ||
  48             vginfo.version < 0x0102)
  49                 return 0;       /* Not present */
  50 
  51         set_fs(vginfo.video_mode_ptr.seg);
  52         mode_ptr = vginfo.video_mode_ptr.off;
  53 
  54         while ((mode = rdfs16(mode_ptr)) != 0xffff) {
  55                 mode_ptr += 2;
  56 
  57                 if (!heap_free(sizeof(struct mode_info)))
  58                         break;  /* Heap full, can't save mode info */
  59 
  60                 if (mode & ~0x1ff)
  61                         continue;
  62 
  63                 memset(&vminfo, 0, sizeof(vminfo)); /* Just in case... */
  64 
  65                 ireg.ax = 0x4f01;
  66                 ireg.cx = mode;
  67                 ireg.di = (size_t)&vminfo;
  68                 intcall(0x10, &ireg, &oreg);
  69 
  70                 if (oreg.ax != 0x004f)
  71                         continue;
  72 
  73                 if ((vminfo.mode_attr & 0x15) == 0x05) {
  74                         /* Text Mode, TTY BIOS supported,
  75                            supported by hardware */
  76                         mi = GET_HEAP(struct mode_info, 1);
  77                         mi->mode  = mode + VIDEO_FIRST_VESA;
  78                         mi->depth = 0; /* text */
  79                         mi->x     = vminfo.h_res;
  80                         mi->y     = vminfo.v_res;
  81                         nmodes++;
  82                 } else if ((vminfo.mode_attr & 0x99) == 0x99 &&
  83                            (vminfo.memory_layout == 4 ||
  84                             vminfo.memory_layout == 6) &&
  85                            vminfo.memory_planes == 1) {
  86 #ifdef CONFIG_FB_BOOT_VESA_SUPPORT
  87                         /* Graphics mode, color, linear frame buffer
  88                            supported.  Only register the mode if
  89                            if framebuffer is configured, however,
  90                            otherwise the user will be left without a screen. */
  91                         mi = GET_HEAP(struct mode_info, 1);
  92                         mi->mode = mode + VIDEO_FIRST_VESA;
  93                         mi->depth = vminfo.bpp;
  94                         mi->x = vminfo.h_res;
  95                         mi->y = vminfo.v_res;
  96                         nmodes++;
  97 #endif
  98                 }
  99         }
 100 
 101         return nmodes;
 102 }
 103 
 104 static int vesa_set_mode(struct mode_info *mode)
 105 {
 106         struct biosregs ireg, oreg;
 107         int is_graphic;
 108         u16 vesa_mode = mode->mode - VIDEO_FIRST_VESA;
 109 
 110         memset(&vminfo, 0, sizeof(vminfo)); /* Just in case... */
 111 
 112         initregs(&ireg);
 113         ireg.ax = 0x4f01;
 114         ireg.cx = vesa_mode;
 115         ireg.di = (size_t)&vminfo;
 116         intcall(0x10, &ireg, &oreg);
 117 
 118         if (oreg.ax != 0x004f)
 119                 return -1;
 120 
 121         if ((vminfo.mode_attr & 0x15) == 0x05) {
 122                 /* It's a supported text mode */
 123                 is_graphic = 0;
 124 #ifdef CONFIG_FB_BOOT_VESA_SUPPORT
 125         } else if ((vminfo.mode_attr & 0x99) == 0x99) {
 126                 /* It's a graphics mode with linear frame buffer */
 127                 is_graphic = 1;
 128                 vesa_mode |= 0x4000; /* Request linear frame buffer */
 129 #endif
 130         } else {
 131                 return -1;      /* Invalid mode */
 132         }
 133 
 134 
 135         initregs(&ireg);
 136         ireg.ax = 0x4f02;
 137         ireg.bx = vesa_mode;
 138         intcall(0x10, &ireg, &oreg);
 139 
 140         if (oreg.ax != 0x004f)
 141                 return -1;
 142 
 143         graphic_mode = is_graphic;
 144         if (!is_graphic) {
 145                 /* Text mode */
 146                 force_x = mode->x;
 147                 force_y = mode->y;
 148                 do_restore = 1;
 149         } else {
 150                 /* Graphics mode */
 151                 vesa_store_mode_params_graphics();
 152         }
 153 
 154         return 0;
 155 }
 156 
 157 
 158 #ifndef _WAKEUP
 159 
 160 /* Switch DAC to 8-bit mode */
 161 static void vesa_dac_set_8bits(void)
 162 {
 163         struct biosregs ireg, oreg;
 164         u8 dac_size = 6;
 165 
 166         /* If possible, switch the DAC to 8-bit mode */
 167         if (vginfo.capabilities & 1) {
 168                 initregs(&ireg);
 169                 ireg.ax = 0x4f08;
 170                 ireg.bh = 0x08;
 171                 intcall(0x10, &ireg, &oreg);
 172                 if (oreg.ax == 0x004f)
 173                         dac_size = oreg.bh;
 174         }
 175 
 176         /* Set the color sizes to the DAC size, and offsets to 0 */
 177         boot_params.screen_info.red_size   = dac_size;
 178         boot_params.screen_info.green_size = dac_size;
 179         boot_params.screen_info.blue_size  = dac_size;
 180         boot_params.screen_info.rsvd_size  = dac_size;
 181 
 182         boot_params.screen_info.red_pos    = 0;
 183         boot_params.screen_info.green_pos  = 0;
 184         boot_params.screen_info.blue_pos   = 0;
 185         boot_params.screen_info.rsvd_pos   = 0;
 186 }
 187 
 188 /* Save the VESA protected mode info */
 189 static void vesa_store_pm_info(void)
 190 {
 191         struct biosregs ireg, oreg;
 192 
 193         initregs(&ireg);
 194         ireg.ax = 0x4f0a;
 195         intcall(0x10, &ireg, &oreg);
 196 
 197         if (oreg.ax != 0x004f)
 198                 return;
 199 
 200         boot_params.screen_info.vesapm_seg = oreg.es;
 201         boot_params.screen_info.vesapm_off = oreg.di;
 202 }
 203 
 204 /*
 205  * Save video mode parameters for graphics mode
 206  */
 207 static void vesa_store_mode_params_graphics(void)
 208 {
 209         /* Tell the kernel we're in VESA graphics mode */
 210         boot_params.screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB;
 211 
 212         /* Mode parameters */
 213         boot_params.screen_info.vesa_attributes = vminfo.mode_attr;
 214         boot_params.screen_info.lfb_linelength = vminfo.logical_scan;
 215         boot_params.screen_info.lfb_width = vminfo.h_res;
 216         boot_params.screen_info.lfb_height = vminfo.v_res;
 217         boot_params.screen_info.lfb_depth = vminfo.bpp;
 218         boot_params.screen_info.pages = vminfo.image_planes;
 219         boot_params.screen_info.lfb_base = vminfo.lfb_ptr;
 220         memcpy(&boot_params.screen_info.red_size,
 221                &vminfo.rmask, 8);
 222 
 223         /* General parameters */
 224         boot_params.screen_info.lfb_size = vginfo.total_memory;
 225 
 226         if (vminfo.bpp <= 8)
 227                 vesa_dac_set_8bits();
 228 
 229         vesa_store_pm_info();
 230 }
 231 
 232 /*
 233  * Save EDID information for the kernel; this is invoked, separately,
 234  * after mode-setting.
 235  */
 236 void vesa_store_edid(void)
 237 {
 238 #ifdef CONFIG_FIRMWARE_EDID
 239         struct biosregs ireg, oreg;
 240 
 241         /* Apparently used as a nonsense token... */
 242         memset(&boot_params.edid_info, 0x13, sizeof(boot_params.edid_info));
 243 
 244         if (vginfo.version < 0x0200)
 245                 return;         /* EDID requires VBE 2.0+ */
 246 
 247         initregs(&ireg);
 248         ireg.ax = 0x4f15;               /* VBE DDC */
 249         /* ireg.bx = 0x0000; */         /* Report DDC capabilities */
 250         /* ireg.cx = 0; */              /* Controller 0 */
 251         ireg.es = 0;                    /* ES:DI must be 0 by spec */
 252         intcall(0x10, &ireg, &oreg);
 253 
 254         if (oreg.ax != 0x004f)
 255                 return;         /* No EDID */
 256 
 257         /* BH = time in seconds to transfer EDD information */
 258         /* BL = DDC level supported */
 259 
 260         ireg.ax = 0x4f15;               /* VBE DDC */
 261         ireg.bx = 0x0001;               /* Read EDID */
 262         /* ireg.cx = 0; */              /* Controller 0 */
 263         /* ireg.dx = 0; */              /* EDID block number */
 264         ireg.es = ds();
 265         ireg.di =(size_t)&boot_params.edid_info; /* (ES:)Pointer to block */
 266         intcall(0x10, &ireg, &oreg);
 267 #endif /* CONFIG_FIRMWARE_EDID */
 268 }
 269 
 270 #endif /* not _WAKEUP */
 271 
 272 static __videocard video_vesa =
 273 {
 274         .card_name      = "VESA",
 275         .probe          = vesa_probe,
 276         .set_mode       = vesa_set_mode,
 277         .xmode_first    = VIDEO_FIRST_VESA,
 278         .xmode_n        = 0x200,
 279 };

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