=================================================== +=+=+=+=+= linux.1.0.1.power-save.patch +=+=+=+=+=+ =================================================== There is some change in v1.1.54, and the original "linux.1.0.power-save.patch" by Christoph Rimek will no longer patch correctly, I finally got a little time to hacked it a little. It should now patch cleanly with v1.1.54 and later... Note: All honor goes to Christoph Rimek. -- James Zhu Change Log: * memsetw() is needed in the new kernel, because it is used in vc_resize which is called in vt.c -- a change in patch v1.1.54 * Patch cleanly with new kernel (v1.1.54 or later ..) . The Following is readme in the original patch from Christoph Rimek: ******** "In my last posting (of 30-apr-94) I published the raw code to support the new generation of monitors that know the VESA Power Saving Protocol (PSP). Recently I found the time to code and can now present: Patch (based on Linux Kernel revision 1.0) for handling the Power Saving feature of the new monitor generation. The code works on all these monitors (mine is a Smile 1506) and should run on *all* video adapter cards (change some i/o-adresses), although tested only on two different VGA-cards: a cheap Cirrus Logic (5428) and a miro Crystal 8S (S3-805). The only affected module is driver/char/console.c and within this the two functions blank_screen and unblank_screen and a few new variable definitions. If activated, the function memsetw is no longer needed. (memsetw() is needed in the new kernel, because it is used in vc_resize() which is called in vt.c -- a change in patch v1.1.54 -- James Zhu ) The file config.in in the main kernel source directory has got two new variables to define: CONFIG_VESA_PSPM (Power Saving Protocol Monitor) and CONFIG_PSPM_FORCE_OFF. I have placed these lines into the character device section right after the SELECTION part. You can choose from two options: (1) CONFIG_VESA_PSPM YES to activate these patches. The code will save the current setting of your video adapters' register settings and then program the controller to turn off the vertical sycnchronisation pulse. For details how this is achived refer to the code fragments following. (2) CONFIG_PSPM_FORCE_OFF If your monitor locally has an Off_Mode timer then you should not force your video card to send the OFF-signal - your monitor will power down by itself. If your monitor cannot handle this and needs the Off-signal directly, or if you like your monitor to power down immediately when the blank_timer times out, then you chose this option. On the other hand I'd recommend to not chose this second option unless it is absolutely necessary. Powering down a monitor to the Off_State with an approx. power consumption of 3-5 Watts is a rather strong action for the CRT and it should not be done every now and then. If the software only sends the signal to enter Standby mode, you have the chance to interfere before the monitor powers down. Do not set a too short period, if you love your hardware :-)) . Another advantage of leaving the power down handling to the monitor is that your always can use the same kernel and change the OFF timeout locally at your monitor. My model lets me chose the timeout in steps of five minutes: 0-5-10-15-... If requested, in the future it may be possible to install another timer to provide a configurable delay between the two stages Standby and Off similar to the "setterm -blank"-feature. After all blah-blah now the diff-outputs for the patches. I'm not sure whether it is necessary to encapsule the saving of the video adapter registers in a cli/sti-pair, while this code comes to execution only when the machine (keyboard) is idle. When setting the registers I think it is better not to allow any interruption of the sequences. Please let me know about your experiences with this code. -cr -- Christoph Rimek, Kiel, Germany (+49 431 18307) chrimek@toppoint.de ***********************************************************************" Good Luck ... James Zhu asolis@csulb.edu (temp. addr) UCF Linux User Group linux@pegasus.cc.ucf.edu * Save the following into two file and patch against: linux/arch/i386/config.in linux/drivers/char/console.c ------------------------- cut here --------------------- *** config.in.orig Sun Jul 24 16:35:21 1994 --- config.in Sun Jul 24 16:36:11 1994 *************** *** 170,175 **** --- 170,184 ---- bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n + + comment 'VESA PSP Power Saving. (Answer yes, only if you have a Green Monitor)' + + bool 'VESA Power Saving Protocol Monitor support' CONFIG_VESA_PSPM n + if [ "$CONFIG_VESA_PSPM" = "y" ]; then + bool 'Force OFF signal to be sent to VESA PSP Monitor' CONFIG_PSPM_FORCE_OFF y + fi + + comment 'Tape Backup Support' bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n if [ "$CONFIG_QIC02_TAPE" = "y" ]; then ------------------------------- cut here ------------------------------ *** console.c.orig Sat Oct 22 18:19:41 1994 --- console.c Sun Oct 23 13:30:11 1994 *************** *** 123,128 **** --- 123,172 ---- static char sel_buffer[SEL_BUFFER_SIZE] = { '\0' }; #endif /* CONFIG_SELECTION */ + #ifdef CONFIG_VESA_PSPM + /* + * This section(s) handles the VESA Power Saving Protocol that let a * + * monitor be powered down whenever not needed for a longer time. * + * VESA protocol defines: * + * * + * Mode/Status HSync VSync Video + * ---------------------------------------------- * + * "On" on on active * + * "Suspend" {either} on off blank + * { or } off on blank + * "Off" off off blank << PSPM_FORCE_OFF * + * * + * Original code taken from the Power Management Utility (PMU) of * + * Huang shi chao, delivered together with many new monitor models * + * capable of the VESA Power Saving Protocol. * + * Adapted to Linux by Christoph Rimek (chrimek@toppoint.de) 15-may-94 + */ + + #define seq_port_reg (0x3c4) /* Sequencer register select port */ + #define seq_port_val (0x3c5) /* Sequencer register value port */ + #define video_misc_rd (0x3cc) /* Video misc. read port */ + #define video_misc_wr (0x3c2) /* Video misc. write port */ + + /* structure holding original VGA register settings */ + static struct { + unsigned char SeqCtrlIndex; /* Sequencer Index reg. */ + unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */ + unsigned char CrtMiscIO; /* Miscellaneous register */ + #ifdef CONFIG_PSPM_FORCE_OFF + unsigned char HorizontalTotal; /* CRT-Controller:00h */ + unsigned char HorizDisplayEnd; /* CRT-Controller:01h */ + unsigned char StartHorizRetrace; /* CRT-Controller:04h */ + unsigned char EndHorizRetrace; /* CRT-Controller:05h */ + #endif + unsigned char Overflow; /* CRT-Controller:07h */ + unsigned char StartVertRetrace; /* CRT-Controller:10h */ + unsigned char EndVertRetrace; /* CRT-Controller:11h */ + unsigned char ModeControl; /* CRT-Controller:17h */ + unsigned char ClockingMode; /* Seq-Controller:01h */ + } vga; + #endif /* CONFIG_VESA_PSPM */ + + #define NPAR 16 static void con_setsize(unsigned long rows, unsigned long cols); *************** *** 287,292 **** --- 331,346 ---- #define vcmode (vt_cons[currcons]->vc_mode) #define structsize (sizeof(struct vc_data) + sizeof(struct vt_struct)) + + /* #ifndef CONFIG_VESA_PSPM */ + /* This function only needed for fast screen buffer filling in */ + /* blank_screen, may be spared if hardware blanks screen. /CR */ + + /**************************************************************************\ + * Note: This function is NEEDED since v1.1.54, it is used in vt_resize() * + * -- a change since v1.1.54 ---- James Zhu * + \**************************************************************************/ + static void * memsetw(void * s, unsigned short c, unsigned int count) { __asm__("cld\n\t" *************** *** 297,302 **** --- 351,357 ---- :"cx","di"); return s; } + /* #endif */ int vc_cons_allocated(unsigned int i) { *************** *** 2025,2031 **** --- 2080,2088 ---- void blank_screen(void) { + #ifndef CONFIG_VESA_PSPM int currcons; + #endif if (console_blanked) return; *************** *** 2036,2041 **** --- 2093,2135 ---- } timer_table[BLANK_TIMER].fn = unblank_screen; + + #ifdef CONFIG_VESA_PSPM + /* save original values of VGA controller registers */ + cli(); + vga.SeqCtrlIndex = inb_p(seq_port_reg); + vga.CrtCtrlIndex = inb_p(video_port_reg); + vga.CrtMiscIO = inb_p(video_misc_rd); + sti(); + #ifdef CONFIG_PSPM_FORCE_OFF + outb_p(0x00,video_port_reg); /* HorizontalTotal */ + vga.HorizontalTotal = inb_p(video_port_val); + outb_p(0x01,video_port_reg); /* HorizDisplayEnd */ + vga.HorizDisplayEnd = inb_p(video_port_val); + outb_p(0x04,video_port_reg); /* StartHorizRetrace */ + vga.StartHorizRetrace = inb_p(video_port_val); + outb_p(0x05,video_port_reg); /* EndHorizRetrace */ + vga.EndHorizRetrace = inb_p(video_port_val); + #endif + outb_p(0x07,video_port_reg); /* Overflow */ + vga.Overflow = inb_p(video_port_val); + outb_p(0x10,video_port_reg); /* StartVertRetrace */ + vga.StartVertRetrace = inb_p(video_port_val); + outb_p(0x11,video_port_reg); /* EndVertRetrace */ + vga.EndVertRetrace = inb_p(video_port_val); + outb_p(0x17,video_port_reg); /* ModeControl */ + vga.ModeControl = inb_p(video_port_val); + outb_p(0x01,seq_port_reg); /* ClockingMode */ + vga.ClockingMode = inb_p(seq_port_val); + + /* assure that video is enabled */ + /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ + cli(); + outb_p(0x01,seq_port_reg); + outb_p(vga.ClockingMode | 0x20,seq_port_val); + sti(); + #else + /* try not to lose information by blanking, and not to waste memory */ currcons = fg_console; has_scrolled = 0; *************** *** 2044,2052 **** set_origin(fg_console); get_scrmem(fg_console); unblank_origin = origin; - memsetw((void *)blank_origin, BLANK, video_mem_term-blank_origin); hide_cursor(); console_blanked = fg_console + 1; } void unblank_screen(void) --- 2138,2183 ---- set_origin(fg_console); get_scrmem(fg_console); unblank_origin = origin; hide_cursor(); + + #endif /* CONFIG_VESA_PSPM */ + console_blanked = fg_console + 1; + + #ifdef CONFIG_VESA_PSPM + cli(); + /* test for vertical retrace in process.... */ + if ((vga.CrtMiscIO & 0x80) == 0x80) + outb_p(vga.CrtMiscIO & 0xef,video_misc_wr); + + /* Set to minimum (0) and * + * to maximum (incl. overflow) * + * Result: turn off vertical sync (VSync) pulse */ + outb_p(0x10,video_port_reg); /* StartVertRetrace */ + outb_p(0xff,video_port_val); /* maximum value */ + outb_p(0x11,video_port_reg); /* EndVertRetrace */ + outb_p(0x40,video_port_val); /* minimum (bits 0..3) */ + outb_p(0x07,video_port_reg); /* Overflow */ + outb_p(vga.Overflow | 0x84,video_port_val); /* bits 9,10 of */ + /* vert. retrace */ + #ifdef CONFIG_PSPM_FORCE_OFF + /* Set to minimum (0) and * + * to maximum * + * Result: turn off horizontal sync (HSync) pulse */ + outb_p(0x04,video_port_reg); /* StartHorizRetrace */ + outb_p(0xff,video_port_val); /* maximum */ + outb_p(0x05,video_port_reg); /* EndHorizRetrace */ + outb_p(0x00,video_port_val); /* minimum (0) */ + #endif + /* restore both index registers */ + outb_p(vga.SeqCtrlIndex,seq_port_reg); + outb_p(vga.CrtCtrlIndex,video_port_reg); + sti(); + #else + memsetw((void *)blank_origin, BLANK, video_mem_term-blank_origin); + + #endif /* CONFIG_VESA_PSPM */ + } void unblank_screen(void) *************** *** 2079,2087 **** --- 2210,2253 ---- } console_blanked = 0; + + #ifdef CONFIG_VESA_PSPM + /* restore original values of VGA controller registers */ + cli(); + outb_p(vga.CrtMiscIO,video_misc_wr); + #ifdef CONFIG_PSPM_FORCE_OFF + outb_p(0x00,video_port_reg); /* HorizontalTotal */ + outb_p(vga.HorizontalTotal,video_port_val); + outb_p(0x01,video_port_reg); /* HorizDisplayEnd */ + outb_p(vga.HorizDisplayEnd,video_port_val); + outb_p(0x04,video_port_reg); /* StartHorizRetrace */ + outb_p(vga.StartHorizRetrace,video_port_val); + outb_p(0x05,video_port_reg); /* EndHorizRetrace */ + outb_p(vga.EndHorizRetrace,video_port_val); + #endif + outb_p(0x07,video_port_reg); /* Overflow */ + outb_p(vga.Overflow,video_port_val); + outb_p(0x10,video_port_reg); /* StartVertRetrace */ + outb_p(vga.StartVertRetrace,video_port_val); + outb_p(0x11,video_port_reg); /* EndVertRetrace */ + outb_p(vga.EndVertRetrace,video_port_val); + outb_p(0x17,video_port_reg); /* ModeControl */ + outb_p(vga.ModeControl,video_port_val); + outb_p(0x01,seq_port_reg); /* ClockingMode */ + outb_p(vga.ClockingMode,seq_port_val); + + /* restore index/control registers */ + outb_p(vga.SeqCtrlIndex,seq_port_reg); + outb_p(vga.CrtCtrlIndex,video_port_reg); + sti(); + #else + set_scrmem(fg_console, offset); set_origin(fg_console); set_cursor(fg_console); + + #endif /* CONFIG_VESA_PSPM */ + if (resetorg) __set_origin(blank__origin); } *************** *** 2458,2465 **** --- 2624,2633 ---- /* Pauline Middelink reports that we should use 0xA0000 for the bwmap as well.. */ #define blackwmap ((char *)0xa0000) #define cmapsz 8192 + #ifndef seq_port_reg /* avoid re-definition */ #define seq_port_reg (0x3c4) #define seq_port_val (0x3c5) + #endif #define gr_port_reg (0x3ce) #define gr_port_val (0x3cf)