/* m300bl.c -- Compaq Armada M300 backlight control (c) 2001, Georg Acher, georg at acher dot org This program adjusts the LCD backlight brightness of the Compaq Armada M300 by changing the PWM output of the FDC37N971 Super-IO-chip. Pin 199 (PWM1) goes straight to the CCFL voltage converter. For further information look at the data sheet of the 37N971. Compile this simple program with 'gcc -O2 -o m300bl m300bl.c', and give it suid-root permission (as root: 'chmod +s m300bl'). Example usage: m300bl - : Decrease brightness one step m300bl + : Increase brightness one step m300bl 8 : Set full brightness #include */ #include #include #include #define INDEX_PORT 0xe0 #define DATA_PORT (INDEX_PORT+1) #define CONF_START 0x55 #define CONF_END 0xAA #define REG_LOGDN 0x07 #define REG_CHIP_ID 0x20 #define REG_LDN_ACT 0x30 #define REG_LDN_BASEH 0x60 #define REG_LDN_BASEL 0x61 #define MBX_PWM0 0x92 #define MBX_PWM1 0x93 void out_idx(int reg, int val) { outb(reg,INDEX_PORT); outb(val,DATA_PORT); } unsigned int in_idx(int reg) { outb(reg,INDEX_PORT); return inb(DATA_PORT); } main(int argc, char **argv) { int n,ldn,id,mode,old; if (argc!=2) { fprintf(stderr, "m300bl (c) Georg Acher, georg @ acher dot org\n" "Sets brightness of M300 LCD backlight\n" "Usage: m300bl <+|-|value>\n" "+/-: Increase/decrease brightness\n", "value: Set brightness (0<=value<=8)\n"); exit(-1); } else if (*argv[1]=='+') mode=-1; else if (*argv[1]=='-') mode=-2; else { mode=atoi(argv[1]); if (mode>8) mode=8; if (mode<0) mode=0; } if( iopl(3) == -1 ) { fprintf(stderr, "%s: could not obtain right to write to ioports.\n" "be sure to run me as root or setuid.\n", argv[0] ); exit(1); } outb(CONF_START,INDEX_PORT); id=in_idx(REG_CHIP_ID); if (id!=0xa && id!=0xb) { fprintf(stderr,"m300bl: Unknown Chip-ID: %02x\n",id); exit(-1); } // Now find register base address of logical device 9 (Mailboxes) ldn=9; // Mailboxes out_idx(REG_LOGDN,ldn); n=(in_idx(REG_LDN_BASEH)<<8)+in_idx(REG_LDN_BASEL); #if 0 printf("Base of LDN %i: %04x\n",ldn,n); printf("Activation of LDN %i: %02x\n",ldn,in_idx(REG_LDN_ACT)); #endif // Get current value of PWM1 outb(MBX_PWM1,n); old=inb(n+1)>>1; if (mode==-1) old=old+8; else if (mode==-2) old=old-8; else { old=mode*8; if (mode==8) old--; } if (old<0) old=0; if (old>63) old=63; outb(old*2,n+1); outb(CONF_END,INDEX_PORT); exit(0); }