howto:
enable speedstepping on an amilo m 1420 (Pentium M 715 - 1,5ghz) with Ubuntu 8.04 - Linux 2.6.24

use this howto on your own risk!!


when i first booted Ubuntu 8.04 on my amilo m 1420 i noticed that i can use just two cpu speedsteps (600mhz and 1,5 ghz) altough my cpu (Pentium M 715) supports 5 steps. on my amilo notebook this is really annoying because of its noisy cpu-fan.
in former times the speedstep-centrino module of the linux-kernel took care of speedstepping. this module also provided the information for the speedsteps. But in kernel 2.6.24 speedstep-centrino is marked as deprecated and its work is done by acpi-cpufreq, which does not provide the information for the speedsteps because it is not the task of the kernel to provide this info. so this is not a kernel bug but a bios bug. thus we have to fix the bios, or more precisely the DSDT/SSDT of the bios. According to the ACPI 3.0 specification either the DSDT or the SSDT should provide the information about the available speedsteps. The SSDT of the amilo m 1420 does include the tables of 2 speedsteps (600mhz and 1.5ghz) but the other 3 speedsteps are just missing. So we have to modify the SSDT and tell linux to load the custom SSDT at boot:

1. install the necessary sofware
	sudo apt-get install acpidump iasl

please keep in mind that modifying you ACPI tables (f.e. the DSDT or SSDT) can _really_ destroy your hardware!!!!

2. write the SSDT and the DSDT from the bios into files on your hd
	sudo acpidump > tables
	acpixtract -sDSDT tables
	acpixtract -sSSDT tables 
now you should have a DSDT.dat and a SSDT.dat file.

3. Disassemble the files.
	iasl -d SSDT.dat 
	iasl -d DSDT.dat
now you got a SSDT.dsl and a DSDT.dsl file

4. merge your SSDT.dsl with your DSDT.dsl
this is necassary because the linux kernel can just load a custom DSDT but not a custom SSDT
you have to comment out three lines of the SSDT.dsl before you merge it with the DSDT. (if this is to complicated you can have a look at my DSDT.dsl at the end of part 7... or you could just use my DSDT.dsl)
change
	DefinitionBlock ("SSDT.aml", "SSDT", 1, "INSYDE", "GV3Ref", 0x00001001)
	 {
        External (\_PR_.CPU0, DeviceObj)
into
	// DefinitionBlock ("SSDT.aml", "SSDT", 1, "INSYDE", "GV3Ref", 0x00001001)
	//  {
	// External (\_PR_.CPU0, DeviceObj)

you also have to comment out the last curly bracket of the DSDT.dsl. so that this file ends with
	// }
after that you just have to add the SSDT.dsl at the end of the DSDT.dsl. you can do this with
	cat SSDT.dsl >> DSDT.dsl

5. set the correct register adress for the PERF_CTL and the PERF_STATUS registers
the PERF_CTL register in the MSR indicates the target frequency and voltage and is locatet at 199.
the PERF_STATUS register indicates the current frequency and voltage and is locatet at 198.
you can find this info in the "Enhanced Intel SpeedStep Technology for the Intel Pentium M Processor" paper at ftp://download.intel.com/design/network/papers/30117401.pdf
you set this adresses by changing
	Else
            {
                Return (Package (0x02)
                {
                    ResourceTemplate ()
                    {
                        Register (FFixedHW,
                            0x00,               // Bit Width
                            0x00,               // Bit Offset
                            0x0000000000000000, // Address
                            ,)
                    },

                    ResourceTemplate ()
                    {
                        Register (FFixedHW,
                            0x00,               // Bit Width
                            0x00,               // Bit Offset
                            0x0000000000000000, // Address
                            ,)
                    }
                })
            }
into
	Else
            {
                Return (Package (0x02)
                {
                    ResourceTemplate ()
                    {
                        Register (FFixedHW,
                            0x10,               // Bit Width
                            0x00,               // Bit Offset
                            0x0000000000000199, // Address
                            ,)
                    },

                    ResourceTemplate ()
                    {
                        Register (FFixedHW,
                            0x10,               // Bit Width
                            0x00,               // Bit Offset
                            0x0000000000000198, // Address
                            ,)
                    }
                })
            }
so the "// Address" lines change... you find this section at the beginning of the SSDT part. but make sure to change the FFixedHW adresses and not the SystemIO adresses!!

6. complete the _PSS table
the _PSS table in the SSDT section of your DSDT file contains the list for the availabe speedsteps.
the first line contains the number of the speedsteps. so you have to change
	Name (_PSS, Package (0x02)
into
	Name (_PSS, Package (0x05)
now you have to add three "Package (0x06)" tables for the three missing speedsteps
each speedstep entry contains six data fields in the following order:

CoreFreq
Power
TransitionLatency
BusMasterLatency
Control
Status

as far as i know for us the first (CoreFreq) and the last two lines (Control, Status) are important.
the first line is the frequncy in HEX. so 5DC for example means 1500.
in the Control line the first 4 bit set the frequency/100. the next 8 bit set the voltage in millivolts * 16 + 700
so for example 612 in the control line measn: 600mhz and voltage = 18 * 16 + 700 = 988 mV (HEX 12 = DEC 18).
the Status line must just be an unique number for each speedstep.
you find the information for the recommended voltages somewhere here: http://www.intel.com/design/mobile/pentiumm/documentation.htm
all in all at the end your _PSS table should look somehow like this:
	Name (_PSS, Package (0x05)
        {
            Package (0x06)
            {
                0x000005DC,
                0x00000000,
                0x00000064,
                0x0000006E,
                0xF27,
                0x00000000
            },

            Package (0x06)
            {
                0x000004B0,
                0x00000000,
                0x00000064,
                0x0000006E,
                0xC21,
                0x00000001
            },

            Package (0x06)
            {
                0x000003E8,
                0x00000000,
                0x00000064,
                0x0000006E,
                0xA1C,
                0x00000002
            },

            Package (0x06)
            {
                0x00000320,
                0x00000000,
                0x00000064,
                0x0000006E,
                0x817,
                0x00000003
            },

            Package (0x06)
            {
                0x00000258,
                0x00000000,
                0x00000064,
                0x0000006E,
                0x612,
                0x00000004
            }
        })

now your DSDT.dsl should look like this: DSDT.dsl
7. compile your costum DSDT.dsl
	iasl -sa DSDT.dsl
now you should have this files: DSDT.aml, DSDT.asm, DSDT.dat, DSDT.dsl iasl gives me one warning. but i ignore this... as long as it is no error.

8. append your DSDT.aml to the initramfs
	sudo cp DSDT.aml /etc/initramfs-tools/DSDT.aml
	sudo update-initramfs -u
9. tell the kernel not to load the SSDT from Bios
you have to boot the kernel with acpi_no_auto_ssdt. for example you can do this by adding acpi_no_auto_ssdt to the # defoptions line in your /boot/grub/menu.lst. with the acpi_no_auto_ssdt option this line normally looks like this.
	# defoptions=quiet splash acpi_no_auto_ssdt
after editing the defoptions in the menu.lst you have to run update-grub
	sudo update-grub
10. reboot

---------------------------------------------------------------------------------------------

now all 5 speedsteps should be available. you can check this with
	cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
this should tell you
1500000 1200000 1000000 800000 600000


if you still have just two speedsteps, you could check if your kernel really loaded the custom DSDT and if the SSDT of the bios was ignored. with
	dmesg | grep DSDT
you should find a line like: ACPI: Table DSDT replaced by host OS
and with
	dmesg | grep SSDT
you should find a line like: ACPI: SSDT ignored due to "acpi_no_auto_ssdt"


Undervolting
if the cpu fan is still too noisy for you, you could untervolt your cpu by setting lower voltage values in the Control line of the _PSS table.
you try the lowest working voltages with phc-linux: http://phc.athousandnights.de/
or with the msr-tools: http://www.kernel.org/pub/linux/utils/cpu/msr-tools/
if you set a too low voltage in your DSDT your pc could freeze during startup... if this happens you have to fix your DSDT with an live-cd. therefore is is more confortable to look for the lowest working voltage with phc-linux or msr-tools (phc-linux is also suitable for daily-use. so you do not necessarily have to modify the voltage in your DSDT)