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. You may set this blanking interval in minutes by
  88     echoing the escape sequence 'ESC[9;interval]' to the terminal.
  89     By default this interval is set to 10 minutes.
  90 
  91     If you use one of these modes, you can also set a second interval
  92     by echoing the escape sequence 'ESC[14;interval]' to the terminal.
  93     The monitor will be turned off completely (mode 3) after being in
  94     suspend mode for the specified interval. An interval of 0 disables
  95     this feature which is the default.
  96 
  97     Both intervals may be set within the range of 0..60 minutes.
  98 
  99 (2) Setting vesa_blanking_mode to 3.
 100     If your monitor locally has an Off_Mode timer then you should not
 101     force your video card to send the OFF-signal - your monitor will
 102     power down by itself.
 103     If your monitor cannot handle this and needs the Off-signal directly,
 104     or if you like your monitor to power down immediately when the
 105     blank_timer times out, then you choose this option.
 106 
 107 On the other hand I'd recommend to not choose this second option unless
 108 it is absolutely necessary. Powering down a monitor to the Off_State with
 109 an approx. power consumption of 3-5 Watts is a rather strong action for
 110 the CRT and it should not be done every now and then. If the software only  
 111 sends the signal to enter Standby mode, you have the chance to interfere
 112 before the monitor powers down. Do not set a too short period, if you love
 113 your hardware :-)) .
 114 
 115 By default vesa_blanking_mode is set to 0, thus not using any power saving
 116 features.
 117 */
 118 
 119 #define seq_port_reg    (0x3c4)         /* Sequencer register select port */
 120 #define seq_port_val    (0x3c5)         /* Sequencer register value port  */
 121 #define video_misc_rd   (0x3cc)         /* Video misc. read port          */
 122 #define video_misc_wr   (0x3c2)         /* Video misc. write port         */
 123 
 124 /* structure holding original VGA register settings */
 125 static struct {
 126         unsigned char   SeqCtrlIndex;           /* Sequencer Index reg.   */
 127         unsigned char   CrtCtrlIndex;           /* CRT-Contr. Index reg.  */
 128         unsigned char   CrtMiscIO;              /* Miscellaneous register */
 129         unsigned char   HorizontalTotal;        /* CRT-Controller:00h */
 130         unsigned char   HorizDisplayEnd;        /* CRT-Controller:01h */
 131         unsigned char   StartHorizRetrace;      /* CRT-Controller:04h */
 132         unsigned char   EndHorizRetrace;        /* CRT-Controller:05h */
 133         unsigned char   Overflow;               /* CRT-Controller:07h */
 134         unsigned char   StartVertRetrace;       /* CRT-Controller:10h */
 135         unsigned char   EndVertRetrace;         /* CRT-Controller:11h */
 136         unsigned char   ModeControl;            /* CRT-Controller:17h */
 137         unsigned char   ClockingMode;           /* Seq-Controller:01h */
 138 } vga;
 139 
 140 #define VESA_NO_BLANKING        0
 141 #define VESA_VSYNC_SUSPEND      1
 142 #define VESA_HSYNC_SUSPEND      2
 143 #define VESA_POWERDOWN          (VESA_HSYNC_SUSPEND | VESA_VSYNC_SUSPEND)
 144 
 145 #define DEFAULT_VESA_BLANKING_MODE      VESA_NO_BLANKING
 146 
 147 static int vesa_blanking_mode = DEFAULT_VESA_BLANKING_MODE;
 148 static int suspend_vesa_blanking_mode = DEFAULT_VESA_BLANKING_MODE;
 149 static int vesa_blanked = 0;
 150 
 151 /* routine to blank a vesa screen */
 152 void vesa_blank(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 153 {
 154         int mode;
 155 
 156         if((mode = vesa_blanking_mode) == 0)
 157           return;
 158 
 159         /* save original values of VGA controller registers */
 160         if(!vesa_blanked) {
 161             cli();
 162             vga.SeqCtrlIndex = inb_p(seq_port_reg);
 163             vga.CrtCtrlIndex = inb_p(video_port_reg);
 164             vga.CrtMiscIO = inb_p(video_misc_rd);
 165             sti();
 166 
 167             outb_p(0x00,video_port_reg);                /* HorizontalTotal */
 168             vga.HorizontalTotal = inb_p(video_port_val);
 169             outb_p(0x01,video_port_reg);                /* HorizDisplayEnd */
 170             vga.HorizDisplayEnd = inb_p(video_port_val);
 171             outb_p(0x04,video_port_reg);                /* StartHorizRetrace */
 172             vga.StartHorizRetrace = inb_p(video_port_val);
 173             outb_p(0x05,video_port_reg);                /* EndHorizRetrace */
 174             vga.EndHorizRetrace = inb_p(video_port_val);
 175             outb_p(0x07,video_port_reg);                /* Overflow */
 176             vga.Overflow = inb_p(video_port_val);
 177             outb_p(0x10,video_port_reg);                /* StartVertRetrace */
 178             vga.StartVertRetrace = inb_p(video_port_val);
 179             outb_p(0x11,video_port_reg);                /* EndVertRetrace */
 180             vga.EndVertRetrace = inb_p(video_port_val);
 181             outb_p(0x17,video_port_reg);                /* ModeControl */
 182             vga.ModeControl = inb_p(video_port_val);
 183             outb_p(0x01,seq_port_reg);                  /* ClockingMode */
 184             vga.ClockingMode = inb_p(seq_port_val);
 185         }
 186 
 187         /* assure that video is enabled */
 188         /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
 189         cli();
 190         outb_p(0x01,seq_port_reg);
 191         outb_p(vga.ClockingMode | 0x20,seq_port_val);
 192 
 193         /* test for vertical retrace in process.... */
 194         if ((vga.CrtMiscIO & 0x80) == 0x80)
 195                 outb_p(vga.CrtMiscIO & 0xef,video_misc_wr);
 196 
 197         /*
 198          * Set <End of vertical retrace> to minimum (0) and
 199          * <Start of vertical Retrace> to maximum (incl. overflow)
 200          * Result: turn off vertical sync (VSync) pulse.
 201          */
 202         if (mode & VESA_VSYNC_SUSPEND) {
 203             outb_p(0x10,video_port_reg);        /* StartVertRetrace */
 204             outb_p(0xff,video_port_val);        /* maximum value */
 205             outb_p(0x11,video_port_reg);        /* EndVertRetrace */
 206             outb_p(0x40,video_port_val);        /* minimum (bits 0..3)  */
 207             outb_p(0x07,video_port_reg);                /* Overflow */
 208             outb_p(vga.Overflow | 0x84,video_port_val); /* bits 9,10 of  */
 209                                                         /* vert. retrace */
 210         }
 211 
 212         if (mode & VESA_HSYNC_SUSPEND) {
 213             /*
 214              * Set <End of horizontal retrace> to minimum (0) and
 215              *  <Start of horizontal Retrace> to maximum
 216              * Result: turn off horizontal sync (HSync) pulse.
 217              */
 218             outb_p(0x04,video_port_reg);        /* StartHorizRetrace */
 219             outb_p(0xff,video_port_val);        /* maximum */
 220             outb_p(0x05,video_port_reg);        /* EndHorizRetrace */
 221             outb_p(0x00,video_port_val);        /* minimum (0) */
 222         }
 223 
 224         /* restore both index registers */
 225         outb_p(vga.SeqCtrlIndex,seq_port_reg);
 226         outb_p(vga.CrtCtrlIndex,video_port_reg);
 227         sti();
 228 
 229         vesa_blanked = mode;
 230 }       
 231 
 232 /* routine to unblank a vesa screen */
 233 void vesa_unblank(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235         if (!vesa_blanked)
 236           return;
 237 
 238         /* restore original values of VGA controller registers */
 239         cli();
 240         outb_p(vga.CrtMiscIO,video_misc_wr);
 241 
 242         outb_p(0x00,video_port_reg);            /* HorizontalTotal */
 243         outb_p(vga.HorizontalTotal,video_port_val);
 244         outb_p(0x01,video_port_reg);            /* HorizDisplayEnd */
 245         outb_p(vga.HorizDisplayEnd,video_port_val);
 246         outb_p(0x04,video_port_reg);            /* StartHorizRetrace */
 247         outb_p(vga.StartHorizRetrace,video_port_val);
 248         outb_p(0x05,video_port_reg);            /* EndHorizRetrace */
 249         outb_p(vga.EndHorizRetrace,video_port_val);
 250         outb_p(0x07,video_port_reg);            /* Overflow */
 251         outb_p(vga.Overflow,video_port_val);
 252         outb_p(0x10,video_port_reg);            /* StartVertRetrace */
 253         outb_p(vga.StartVertRetrace,video_port_val);
 254         outb_p(0x11,video_port_reg);            /* EndVertRetrace */
 255         outb_p(vga.EndVertRetrace,video_port_val);
 256         outb_p(0x17,video_port_reg);            /* ModeControl */
 257         outb_p(vga.ModeControl,video_port_val);
 258         outb_p(0x01,seq_port_reg);              /* ClockingMode */
 259         outb_p(vga.ClockingMode,seq_port_val);
 260 
 261         /* restore index/control registers */
 262         outb_p(vga.SeqCtrlIndex,seq_port_reg);
 263         outb_p(vga.CrtCtrlIndex,video_port_reg);
 264         sti();
 265 
 266         vesa_blanked = 0;
 267 }
 268 
 269 void set_vesa_blanking(const unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 270 {
 271         unsigned char *argp = (unsigned char *)(arg + 1);
 272         unsigned int mode = get_user(argp);
 273         vesa_blanking_mode = suspend_vesa_blanking_mode =
 274                 ((mode <= VESA_POWERDOWN) ? mode : DEFAULT_VESA_BLANKING_MODE);
 275 }
 276 
 277 void vesa_powerdown(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 278 {
 279         if(vesa_blanking_mode == VESA_VSYNC_SUSPEND
 280                 || vesa_blanking_mode == VESA_HSYNC_SUSPEND)
 281         {
 282                 vesa_blanking_mode = VESA_POWERDOWN;
 283                 vesa_blank();
 284                 vesa_blanking_mode = suspend_vesa_blanking_mode;
 285         }
 286 }

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