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

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

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