root/drivers/char/vesa_blank.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vesa_blank
  2. vesa_unblank
  3. set_vesa_blanking
  4. vesa_powerdown

   1 /*
   2  * vesa_blank.c
   3  *
   4  * Exported functions:
   5  *      void vesa_blank(void);
   6  *      void vesa_unblank(void);
   7  *      void vesa_powerdown(void);
   8  *      void set_vesa_blanking(const unsigned long arg);
   9  *
  10  * Not all hardware reacts well to this code - activate at your own risk.
  11  * Activation is done using a sufficiently recent version of setterm
  12  * or using a tiny C program like the following.
  13  *
  14 -----------------------------------------------------------------------
  15 |#include <stdio.h>
  16 |#include <linux/termios.h>
  17 |main(int argc, char *argv[]) {
  18 |    int fd;
  19 |    struct { char ten, onoff; } arg;
  20 |
  21 |    if (argc != 2) {
  22 |       fprintf(stderr, "usage: setvesablank on|vsync|hsync|powerdown|off\n");
  23 |       exit(1);
  24 |    }
  25 |    if ((fd = open("/dev/console", 0)) < 0)
  26 |      fd = 0;
  27 |    arg.ten = 10;
  28 |    arg.onoff = 0;
  29 |    if (!strcmp(argv[1], "on"))
  30 |      arg.onoff = 1;
  31 |    else if (!strcmp(argv[1], "vsync"))
  32 |      arg.onoff = 1;
  33 |    else if (!strcmp(argv[1], "hsync"))
  34 |      arg.onoff = 2;
  35 |    else if (!strcmp(argv[1], "powerdown"))
  36 |      arg.onoff = 3;
  37 |    if (ioctl(fd, TIOCLINUX, &arg)) {
  38 |       perror("setvesablank: TIOCLINUX");
  39 |       exit(1);
  40 |    }
  41 |    exit(0);
  42 |}
  43 -----------------------------------------------------------------------
  44 */
  45 
  46 #include <asm/io.h>
  47 #include <asm/system.h>
  48 #include <asm/segment.h>
  49 
  50 extern unsigned short video_port_reg, video_port_val;
  51 
  52 /*
  53  * This file handles the VESA Power Saving Protocol that lets a
  54  * monitor be powered down whenever not needed for a longer time.
  55  * The VESA protocol defines:
  56  *
  57  *  Mode/Status         HSync   VSync   Video
  58  *  -------------------------------------------
  59  *  "On"                on      on      active  (mode 0)
  60  *  "Suspend" {either}  on      off     blank   (mode 1)
  61  *            {  or  }  off     on      blank   (mode 2)
  62  *  "Off"               off     off     blank   (mode 3)
  63  *
  64  * Original code taken from the Power Management Utility (PMU) of
  65  * Huang shi chao, delivered together with many new monitor models
  66  * capable of the VESA Power Saving Protocol.
  67  *
  68  * Adapted to Linux by Christoph Rimek (chrimek@toppoint.de)  15-may-94.
  69  * A slightly adapted fragment of his README follows.
  70  *
  71  * Two-stage blanking by todd j. derr (tjd@barefoot.org)      10-oct-95.
  72 
  73 Patch (based on Linux Kernel revision 1.0) for handling the Power Saving
  74 feature of the new monitor generation. The code works on all these monitors
  75 (mine is a Smile 1506) and should run on *all* video adapter cards (change
  76 some i/o-addresses), although tested only on two different VGA-cards: a  
  77 cheap Cirrus Logic (5428) and a miro Crystal 8S (S3-805).
  78 
  79 You can choose from two options:
  80 
  81 (1) Setting vesa_blanking_mode to 1 or 2.
  82     The code will save the current setting of your video adapters'
  83     register settings and then program the controller to turn off
  84     the vertical synchronization pulse (mode 1) or horizontal
  85     synchronization pulse (mode 2).  Mode 1 should work with most
  86     monitors, but the VESA spec allows mode 2, so it's included for
  87     completeness.
  88 
  89     If you use one of these modes, you can also set a second interval
  90     by echoing the escape sequence ESC[10;interval] to the terminal.
  91     The monitor will be turned off completely (mode 3) after being in
  92     suspend mode for the specified interval.  The interval defaults to
  93     60 minutes. An interval of 0 disables this feature.
  94 
  95 (2) Setting vesa_blanking_mode to 3.
  96     If your monitor locally has an Off_Mode timer then you should not
  97     force your video card to send the OFF-signal - your monitor will
  98     power down by itself.
  99     If your monitor cannot handle this and needs the Off-signal directly,
 100     or if you like your monitor to power down immediately when the
 101     blank_timer times out, then you choose this option.
 102 
 103 On the other hand I'd recommend to not choose this second option unless
 104 it is absolutely necessary. Powering down a monitor to the Off_State with
 105 an approx. power consumption of 3-5 Watts is a rather strong action for
 106 the CRT and it should not be done every now and then. If the software only  
 107 sends the signal to enter Standby mode, you have the chance to interfere
 108 before the monitor powers down. Do not set a too short period, if you love
 109 your hardware :-)) .
 110 
 111 */
 112 
 113 #define seq_port_reg    (0x3c4)         /* Sequencer register select port */
 114 #define seq_port_val    (0x3c5)         /* Sequencer register value port  */
 115 #define video_misc_rd   (0x3cc)         /* Video misc. read port          */
 116 #define video_misc_wr   (0x3c2)         /* Video misc. write port         */
 117 
 118 /* structure holding original VGA register settings */
 119 static struct {
 120         unsigned char   SeqCtrlIndex;           /* Sequencer Index reg.   */
 121         unsigned char   CrtCtrlIndex;           /* CRT-Contr. Index reg.  */
 122         unsigned char   CrtMiscIO;              /* Miscellaneous register */
 123         unsigned char   HorizontalTotal;        /* CRT-Controller:00h */
 124         unsigned char   HorizDisplayEnd;        /* CRT-Controller:01h */
 125         unsigned char   StartHorizRetrace;      /* CRT-Controller:04h */
 126         unsigned char   EndHorizRetrace;        /* CRT-Controller:05h */
 127         unsigned char   Overflow;               /* CRT-Controller:07h */
 128         unsigned char   StartVertRetrace;       /* CRT-Controller:10h */
 129         unsigned char   EndVertRetrace;         /* CRT-Controller:11h */
 130         unsigned char   ModeControl;            /* CRT-Controller:17h */
 131         unsigned char   ClockingMode;           /* Seq-Controller:01h */
 132 } vga;
 133 
 134 #define VESA_NO_BLANKING        0
 135 #define VESA_VSYNC_SUSPEND      1
 136 #define VESA_HSYNC_SUSPEND      2
 137 #define VESA_POWERDOWN          (VESA_HSYNC_SUSPEND | VESA_VSYNC_SUSPEND)
 138 
 139 #define DEFAULT_VESA_BLANKING_MODE      VESA_NO_BLANKING
 140 
 141 static int vesa_blanking_mode = DEFAULT_VESA_BLANKING_MODE;
 142 static int suspend_vesa_blanking_mode = DEFAULT_VESA_BLANKING_MODE;
 143 static int vesa_blanked = 0;
 144 
 145 /* routine to blank a vesa screen */
 146 void vesa_blank(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 147 {
 148         int mode;
 149 
 150         if((mode = vesa_blanking_mode) == 0)
 151           return;
 152 
 153         /* save original values of VGA controller registers */
 154         if(!vesa_blanked) {
 155             cli();
 156             vga.SeqCtrlIndex = inb_p(seq_port_reg);
 157             vga.CrtCtrlIndex = inb_p(video_port_reg);
 158             vga.CrtMiscIO = inb_p(video_misc_rd);
 159             sti();
 160 
 161             outb_p(0x00,video_port_reg);                /* HorizontalTotal */
 162             vga.HorizontalTotal = inb_p(video_port_val);
 163             outb_p(0x01,video_port_reg);                /* HorizDisplayEnd */
 164             vga.HorizDisplayEnd = inb_p(video_port_val);
 165             outb_p(0x04,video_port_reg);                /* StartHorizRetrace */
 166             vga.StartHorizRetrace = inb_p(video_port_val);
 167             outb_p(0x05,video_port_reg);                /* EndHorizRetrace */
 168             vga.EndHorizRetrace = inb_p(video_port_val);
 169             outb_p(0x07,video_port_reg);                /* Overflow */
 170             vga.Overflow = inb_p(video_port_val);
 171             outb_p(0x10,video_port_reg);                /* StartVertRetrace */
 172             vga.StartVertRetrace = inb_p(video_port_val);
 173             outb_p(0x11,video_port_reg);                /* EndVertRetrace */
 174             vga.EndVertRetrace = inb_p(video_port_val);
 175             outb_p(0x17,video_port_reg);                /* ModeControl */
 176             vga.ModeControl = inb_p(video_port_val);
 177             outb_p(0x01,seq_port_reg);                  /* ClockingMode */
 178             vga.ClockingMode = inb_p(seq_port_val);
 179         }
 180 
 181         /* assure that video is enabled */
 182         /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
 183         cli();
 184         outb_p(0x01,seq_port_reg);
 185         outb_p(vga.ClockingMode | 0x20,seq_port_val);
 186 
 187         /* test for vertical retrace in process.... */
 188         if ((vga.CrtMiscIO & 0x80) == 0x80)
 189                 outb_p(vga.CrtMiscIO & 0xef,video_misc_wr);
 190 
 191         /*
 192          * Set <End of vertical retrace> to minimum (0) and
 193          * <Start of vertical Retrace> to maximum (incl. overflow)
 194          * Result: turn off vertical sync (VSync) pulse.
 195          */
 196         if (mode & VESA_VSYNC_SUSPEND) {
 197             outb_p(0x10,video_port_reg);        /* StartVertRetrace */
 198             outb_p(0xff,video_port_val);        /* maximum value */
 199             outb_p(0x11,video_port_reg);        /* EndVertRetrace */
 200             outb_p(0x40,video_port_val);        /* minimum (bits 0..3)  */
 201             outb_p(0x07,video_port_reg);                /* Overflow */
 202             outb_p(vga.Overflow | 0x84,video_port_val); /* bits 9,10 of  */
 203                                                         /* vert. retrace */
 204         }
 205 
 206         if (mode & VESA_HSYNC_SUSPEND) {
 207             /*
 208              * Set <End of horizontal retrace> to minimum (0) and
 209              *  <Start of horizontal Retrace> to maximum
 210              * Result: turn off horizontal sync (HSync) pulse.
 211              */
 212             outb_p(0x04,video_port_reg);        /* StartHorizRetrace */
 213             outb_p(0xff,video_port_val);        /* maximum */
 214             outb_p(0x05,video_port_reg);        /* EndHorizRetrace */
 215             outb_p(0x00,video_port_val);        /* minimum (0) */
 216         }
 217 
 218         /* restore both index registers */
 219         outb_p(vga.SeqCtrlIndex,seq_port_reg);
 220         outb_p(vga.CrtCtrlIndex,video_port_reg);
 221         sti();
 222 
 223         vesa_blanked = mode;
 224 }       
 225 
 226 /* routine to unblank a vesa screen */
 227 void vesa_unblank(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 228 {
 229         if (!vesa_blanked)
 230           return;
 231 
 232         /* restore original values of VGA controller registers */
 233         cli();
 234         outb_p(vga.CrtMiscIO,video_misc_wr);
 235 
 236         outb_p(0x00,video_port_reg);            /* HorizontalTotal */
 237         outb_p(vga.HorizontalTotal,video_port_val);
 238         outb_p(0x01,video_port_reg);            /* HorizDisplayEnd */
 239         outb_p(vga.HorizDisplayEnd,video_port_val);
 240         outb_p(0x04,video_port_reg);            /* StartHorizRetrace */
 241         outb_p(vga.StartHorizRetrace,video_port_val);
 242         outb_p(0x05,video_port_reg);            /* EndHorizRetrace */
 243         outb_p(vga.EndHorizRetrace,video_port_val);
 244         outb_p(0x07,video_port_reg);            /* Overflow */
 245         outb_p(vga.Overflow,video_port_val);
 246         outb_p(0x10,video_port_reg);            /* StartVertRetrace */
 247         outb_p(vga.StartVertRetrace,video_port_val);
 248         outb_p(0x11,video_port_reg);            /* EndVertRetrace */
 249         outb_p(vga.EndVertRetrace,video_port_val);
 250         outb_p(0x17,video_port_reg);            /* ModeControl */
 251         outb_p(vga.ModeControl,video_port_val);
 252         outb_p(0x01,seq_port_reg);              /* ClockingMode */
 253         outb_p(vga.ClockingMode,seq_port_val);
 254 
 255         /* restore index/control registers */
 256         outb_p(vga.SeqCtrlIndex,seq_port_reg);
 257         outb_p(vga.CrtCtrlIndex,video_port_reg);
 258         sti();
 259 
 260         vesa_blanked = 0;
 261 }
 262 
 263 void set_vesa_blanking(const unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 264 {
 265         unsigned char *argp = (unsigned char *)(arg + 1);
 266         unsigned int mode = get_user(argp);
 267         vesa_blanking_mode = suspend_vesa_blanking_mode =
 268                 ((mode <= VESA_POWERDOWN) ? mode : DEFAULT_VESA_BLANKING_MODE);
 269 }
 270 
 271 void vesa_powerdown(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 272 {
 273         if(vesa_blanking_mode == VESA_VSYNC_SUSPEND
 274                 || vesa_blanking_mode == VESA_HSYNC_SUSPEND)
 275         {
 276                 vesa_blanking_mode = VESA_POWERDOWN;
 277                 vesa_blank();
 278                 vesa_blanking_mode = suspend_vesa_blanking_mode;
 279         }
 280 }

/* [previous][next][first][last][top][bottom][index][help] */