home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / drivers / char / vesa_blank.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-09  |  8.5 KB  |  247 lines

  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)
  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)
  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)
  242. {
  243.     char *argp = (char *)(arg + 1);
  244.     unsigned int mode = get_fs_byte(argp);
  245.     vesa_blanking_mode = ((mode < 3) ? mode : 0);
  246. }
  247.