diff --git a/headers/private/device/power_managment.h b/headers/private/device/power_managment.h new file mode 100644 index 0000000000..2e5cc0c974 --- /dev/null +++ b/headers/private/device/power_managment.h @@ -0,0 +1,39 @@ +#ifndef POWER_MANAGMENT_H +#define POWER_MANAGMENT_H + +#include + +// io controls +enum { + // ioctl response with kMagicFreqID + IDENTIFY_DEVICE = B_DEVICE_OP_CODES_END + 20001, + + // CPU Frequence: + // get a list of freq_info, the list is terminated with a element with + // frequency = 0 + GET_CPU_FREQ_STATES = B_DEVICE_OP_CODES_END + 20005, + // get and set a freq_info + GET_CURENT_CPU_FREQ_STATE, + SET_CPU_FREQ_STATE, + // start watching for frequency changes, ioctl blocks until the frequency + // has changed + WATCH_CPU_FREQ, + // stop all watching ioctl, ioctl return B_ERROR + STOP_WATCHING_CPU_FREQ +}; + +// CPU Frequence: +// magic id returned by IDENTIFY_DEVICE +const uint32 kMagicFreqID = 48921; + +#define MAX_CPU_FREQUENCY_STATES 10 + +typedef struct { + uint16 frequency; // [Mhz] + uint16 volts; + uint16 id; + int power; +} freq_info; + + +#endif diff --git a/src/add-ons/kernel/drivers/power/Jamfile b/src/add-ons/kernel/drivers/power/Jamfile index 0142afad3d..d01eaa904d 100644 --- a/src/add-ons/kernel/drivers/power/Jamfile +++ b/src/add-ons/kernel/drivers/power/Jamfile @@ -3,3 +3,4 @@ SubDir HAIKU_TOP src add-ons kernel drivers power ; SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_button ; SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_lid ; SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_thermal ; +SubInclude HAIKU_TOP src add-ons kernel drivers power enhanced_speedstep ; diff --git a/src/add-ons/kernel/drivers/power/enhanced_speedstep/Jamfile b/src/add-ons/kernel/drivers/power/enhanced_speedstep/Jamfile new file mode 100644 index 0000000000..81878167d9 --- /dev/null +++ b/src/add-ons/kernel/drivers/power/enhanced_speedstep/Jamfile @@ -0,0 +1,18 @@ +SubDir HAIKU_TOP src add-ons kernel drivers power enhanced_speedstep ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +if $(TARGET_PLATFORM) != haiku { + # Needed for . Unfortunately we also get the other headers there, + # that we don't really want. + UsePublicHeaders drivers ; +} + +UsePrivateHeaders kernel ; + +KernelAddon enhanced_speedstep : + enhanced_speedstep.cpp + frequency.cpp + ; + +Depends acpi_enhanced_speedstep : acpi ; \ No newline at end of file diff --git a/src/add-ons/kernel/drivers/power/enhanced_speedstep/enhanced_speedstep.cpp b/src/add-ons/kernel/drivers/power/enhanced_speedstep/enhanced_speedstep.cpp new file mode 100644 index 0000000000..539a7df4af --- /dev/null +++ b/src/add-ons/kernel/drivers/power/enhanced_speedstep/enhanced_speedstep.cpp @@ -0,0 +1,425 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include "enhanced_speedstep.h" +#include + +#include "frequency.h" + + +#define EST_MODULE_NAME "drivers/power/enhanced_speedstep/driver_v1" + +#define EST_DEVICE_MODULE_NAME "drivers/power/enhanced_speedstep/device_v1" + +/* Base Namespace devices are published to */ +#define EST_BASENAME "power/enhanced_speedstep/%d" + +// name of pnp generator of path ids +#define EST_PATHID_GENERATOR "est/path_id" + +static device_manager_info *sDeviceManager; +static ConditionVariable cv_frequency; +vint32 current_id; + +status_t est_control(void* _cookie, uint32 op, void* arg, size_t len); + + +static status_t +est_open(void *initCookie, const char *path, int flags, void** cookie) +{ + TRACE("est: open\n"); + est_cookie *device = (est_cookie*)initCookie; + *cookie = device; + device->stop_watching = 0; + + // enable enhanced speedstep + TRACE("est: check if enhanced speedstep is enabled\n"); + uint64 msrMisc = x86_read_msr(MSR_MISC); + if ((msrMisc & MSR_EST_ENABLED) == 0) { + TRACE("est: enable enhanced speedstep\n"); + x86_write_msr(MSR_MISC, msrMisc | MSR_EST_ENABLED); + + uint64 msrMisc = x86_read_msr(MSR_MISC); + if ((msrMisc & MSR_EST_ENABLED) == 0) { + TRACE("est: enable enhanced speedstep failed\n"); + return B_ERROR; + } + } + + // get freq_info + if (est_get_info(&(device->available_states)) != B_OK) + return B_ERROR; + freq_info *freqsInfo = device->available_states; + + // count number of states + TRACE("est: frequency info:\n"); + freq_info *f; + device->number_states = 0; + for (f = freqsInfo; f->frequency != 0; f++) { + TRACE("est: Frequency %u, Volts %u, Power %i, Latency %u, id %u\n", + f->frequency, f->volts, f->power, f->id, EST_TRANS_LAT); + device->number_states++; + } + + // print current frequency + freq_info *f2 = est_get_current(freqsInfo); + if (f2) { + TRACE("est: Current Frequency %u, Volts %u, Power %i, Latency %u\n", + f2->frequency, f2->volts, f2->power, EST_TRANS_LAT); + } + + return B_OK; +} + + +static status_t +est_read(void* _cookie, off_t position, void *buf, size_t* num_bytes) +{ + TRACE("est: est_read\n"); + + if (*num_bytes < 1) + return B_IO_ERROR; + + est_cookie *device = (est_cookie *)_cookie; + + if (position == 0) { + size_t max_len = *num_bytes; + char *str = (char *)buf; + + snprintf(str, max_len, "CPU Frequency states:\n"); + max_len-= strlen(str); + str += strlen(str); + + freq_info *freqsInfo = device->available_states; + freq_info *f; + for (f = freqsInfo; f->frequency != 0; f++) { + snprintf(str, max_len, " Frequency %hu, Volts %hu, Power %i, Latency %i, id %hu\n", + f->frequency, f->volts, f->power, f->id, + EST_TRANS_LAT); + max_len-= strlen(str); + str += strlen(str); + } + + freq_info *f2 = est_get_current(freqsInfo); + if (f2) { + snprintf(str, max_len, "\nCurrent State: Frequency %hu, Volts %hu, Power %i, Latency %i\n", + f2->frequency, f2->volts, f2->power, EST_TRANS_LAT); + } + + *num_bytes = strlen((char *)buf); + } else { + *num_bytes = 0; + } + + return B_OK; +} + + +static status_t +est_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes) +{ + return B_ERROR; +} + + +status_t +est_control(void* _cookie, uint32 op, void* arg, size_t len) +{ + TRACE("est: est_control op %u\n", int(op)); + est_cookie* device = (est_cookie*)_cookie; + status_t err = B_ERROR; + + uint32* magicId; + uint16* id; + freq_info* freqInfo = NULL; + switch (op) { + case IDENTIFY_DEVICE: + if (len < sizeof(uint32)) + return B_IO_ERROR; + magicId = (uint32*)arg; + *magicId = kMagicFreqID; + err = B_OK; + break; + + case GET_CPU_FREQ_STATES: + if (len < sizeof(freq_info) * (device->number_states + 1)) + return B_IO_ERROR; + freqInfo = (freq_info*)arg; + user_memcpy(freqInfo, device->available_states, + sizeof(freq_info) * (device->number_states + 1)); + err = B_OK; + break; + + case GET_CURENT_CPU_FREQ_STATE: + if (len < sizeof(uint16)) + return B_IO_ERROR; + freqInfo = est_get_current(device->available_states); + if (!freqInfo) + return B_ERROR; + atomic_set(¤t_id, freqInfo->id); + *((uint16*)arg) = freqInfo->id; + err = B_OK; + break; + + case SET_CPU_FREQ_STATE: + if (len < sizeof(uint16)) + return B_IO_ERROR; + id = (uint16*)arg; + err = est_set_id16(*id); + if (err == B_OK) { + atomic_set(¤t_id, *id); + cv_frequency.NotifyAll(); + } + break; + + case WATCH_CPU_FREQ: + if (len < sizeof(uint16)) + return B_IO_ERROR; + cv_frequency.Wait(); + if (atomic_get(&(device->stop_watching))) { + atomic_set(&(device->stop_watching), 0); + err = B_ERROR; + } + else { + *((uint16*)arg) = atomic_get(¤t_id); + err = B_OK; + } + break; + + case STOP_WATCHING_CPU_FREQ: + atomic_set(&(device->stop_watching), 1); + cv_frequency.NotifyAll(); + err = B_OK; + break; + } + return err; +} + + +static status_t +est_close (void* cookie) +{ + return B_OK; +} + + +static status_t +est_free (void* cookie) +{ + return B_OK; +} + + +// #pragma mark - driver module API + + +static float +est_support(device_node *parent) +{ + const char *bus; + uint32 device_type; + +dprintf("EST1\n"); + // make sure parent is really the ACPI bus manager + if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) + return -1; +dprintf("EST2\n"); + + if (strcmp(bus, "acpi")) + return 0.0; +dprintf("EST3\n"); + + // check whether it's really a cpu Device + if (sDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM, + &device_type, false) != B_OK + || device_type != ACPI_TYPE_PROCESSOR) { + return 0.0; + } +dprintf("EST4\n"); + TRACE("est_support: supported\n"); + + // check if cpu support est + uint32 cpuNum = 0; + system_info sysInfo; + if (get_system_info(&sysInfo) != B_OK) + return 0.0; + TRACE("cpu_type: %u vendor %u model %u\n", sysInfo.cpu_type, + sysInfo.cpu_type & B_CPU_x86_VENDOR_MASK, + sysInfo.cpu_type & 0x00FF); +dprintf("EST5\n"); + if ((sysInfo.cpu_type & B_CPU_x86_VENDOR_MASK) != B_CPU_INTEL_x86) + return 0.0; +dprintf("EST6\n"); + + TRACE("ext\n"); + cpuid_info info; + if (get_cpuid(&info, 1, cpuNum) != B_OK) + return 0.0; +dprintf("EST7\n"); + + TRACE("extended_features: %i\n", int(info.eax_1.extended_features)); +dprintf("EST8\n"); + + // check for enhanced speedstep + if (info.eax_1.extended_features & IA32_FEATURE_EXT_EST) + TRACE("supprot est\n"); + else + return 0.0; +dprintf("EST9\n"); + + TRACE("success\n"); + + return 0.6; +} + + +static status_t +est_register_device(device_node *node) +{ + device_attr attrs[] = { + { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, + { string: "ACPI Enhanced Speedstep" }}, + { NULL } + }; + + return sDeviceManager->register_node(node, EST_MODULE_NAME, attrs, + NULL, NULL); +} + + +static status_t +est_init_driver(device_node *node, void **_driverCookie) +{ + *_driverCookie = node; + + cv_frequency.Init(NULL, "frequency cv"); + current_id = -1; + + return B_OK; +} + + +static void +est_uninit_driver(void *driverCookie) +{ +} + + +static status_t +est_register_child_devices(void *_cookie) +{ + device_node *node = (device_node*)_cookie; + int path_id; + char name[128]; + + path_id = sDeviceManager->create_id(EST_PATHID_GENERATOR); + if (path_id < 0) { + TRACE("est_register_child_devices: couldn't create a path_id\n"); + return B_ERROR; + } + + snprintf(name, sizeof(name), EST_BASENAME, path_id); + + return sDeviceManager->publish_device(node, name, EST_DEVICE_MODULE_NAME); +} + + +static status_t +est_init_device(void *driverCookie, void **cookie) +{ + est_cookie *device; + device = (est_cookie *)calloc(1, sizeof(est_cookie)); + if (device == NULL) + return B_NO_MEMORY; + *cookie = device; + + device_node *node = (device_node *)driverCookie; + device->node = node; + + device_node *parent; + parent = sDeviceManager->get_parent_node(node); + sDeviceManager->get_driver(parent, (driver_module_info **)&device->acpi, + (void **)&device->acpi_cookie); + sDeviceManager->put_node(parent); + + return B_OK; +} + + +static void +est_uninit_device(void *_cookie) +{ + TRACE("est: est_uninit_device\n"); + est_cookie *device = (est_cookie*)_cookie; + free(device); +} + + + +module_dependency module_dependencies[] = { + { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager }, + {} +}; + + +driver_module_info est_driver_module = { + { + EST_MODULE_NAME, + 0, + NULL + }, + + est_support, + est_register_device, + est_init_driver, + est_uninit_driver, + est_register_child_devices, + NULL, // rescan + NULL, // removed +}; + + +struct device_module_info est_device_module = { + { + EST_DEVICE_MODULE_NAME, + 0, + NULL + }, + + est_init_device, + est_uninit_device, + NULL, + + est_open, + est_close, + est_free, + est_read, + est_write, + NULL, + est_control, + + NULL, + NULL +}; + +module_info *modules[] = { + (module_info *)&est_driver_module, + (module_info *)&est_device_module, + NULL +}; diff --git a/src/add-ons/kernel/drivers/power/enhanced_speedstep/enhanced_speedstep.h b/src/add-ons/kernel/drivers/power/enhanced_speedstep/enhanced_speedstep.h new file mode 100644 index 0000000000..d511f38dd7 --- /dev/null +++ b/src/add-ons/kernel/drivers/power/enhanced_speedstep/enhanced_speedstep.h @@ -0,0 +1,29 @@ +#ifndef _EST_H +#define _EST_H + +#include +#include + +#include "frequency.h" + +// Model Specific Register +#define MSR_MISC 0x1a0 +#define MSR_EST_ENABLED (1<<16) + + +struct est_cookie { + // this three variables are not needed yet but helpfull when extend this + // driver to use acpi + device_node *node; + acpi_device_module_info *acpi; + acpi_device acpi_cookie; + + // array of states don't delete it + freq_info* available_states; + uint8 number_states; + + vint32 stop_watching; +}; + + +#endif /* _EST_H */ diff --git a/src/add-ons/kernel/drivers/power/enhanced_speedstep/frequency.cpp b/src/add-ons/kernel/drivers/power/enhanced_speedstep/frequency.cpp new file mode 100644 index 0000000000..63d45f8ce5 --- /dev/null +++ b/src/add-ons/kernel/drivers/power/enhanced_speedstep/frequency.cpp @@ -0,0 +1,197 @@ +#include "frequency.h" + +#include + +#include +#include +#include + + +void +est_get_id16(uint16 *id16_p) +{ + *id16_p = x86_read_msr(MSR_GET_FREQ_STATE) & 0xffff; +} + + +status_t +est_set_id16(uint16 id16, bool need_check) +{ + uint64 msr; + + // Read the current register, mask out the old, set the new id. + msr = x86_read_msr(MSR_GET_FREQ_STATE); + msr = (msr & ~0xffff) | id16; + x86_write_msr(MSR_SET_FREQ_STATE, msr); + + if (need_check) { + // Wait a short while for the new setting. XXX Is this necessary? + snooze(EST_TRANS_LAT); + + uint16 new_id16; + est_get_id16(&new_id16); + if (new_id16 != id16) + return B_ERROR; + TRACE("EST: set frequency ok, id %i\n", id16); + } + return B_OK; +} + + +freq_info * +est_get_current(freq_info *freq_list) +{ + freq_info *f; + int i; + uint16 id16; + + /* + * Try a few times to get a valid value. Sometimes, if the CPU + * is in the middle of an asynchronous transition (i.e., P4TCC), + * we get a temporary invalid result. + */ + for (i = 0; i < 5; i++) { + est_get_id16(&id16); + for (f = freq_list; f->id != 0; f++) { + if (f->id == id16) + return (f); + } + snooze(100); + } + return NULL; +} + + +status_t +est_get_info(freq_info **freqsInfo) +{ + uint64 msr; + status_t error = B_ERROR; + + msr = x86_read_msr(MSR_GET_FREQ_STATE); + error = est_table_info(msr, freqsInfo); + if (error != B_OK) { + TRACE("EST: Get frequency table from model specific register\n"); + error = est_msr_info(msr, freqsInfo); + } + + if (error) { + TRACE("est: CPU supports Enhanced Speedstep, but is not recognized.\n"); + return error; + } + + return B_OK; +} + + +status_t +est_table_info(uint64 msr, freq_info **freqs) +{ + ss_cpu_info *p; + uint32 id; + + /* Find a table which matches (vendor, id32). */ + system_info sysInfo; + if (get_system_info(&sysInfo) != B_OK) + return B_ERROR; + id = msr >> 32; + for (p = ESTprocs; p->id32 != 0; p++) { + if (p->vendor_id == uint32(sysInfo.cpu_type & B_CPU_x86_VENDOR_MASK) + && p->id32 == id) + break; + } + if (p->id32 == 0) + return B_ERROR; + + /* Make sure the current setpoint is valid. */ + if (est_get_current(p->freqtab) == NULL) { + TRACE("current setting not found in table\n"); + return B_ERROR; + } + + *freqs = p->freqtab; + return B_OK; +} + + +bool +bus_speed_ok(int bus) +{ + switch (bus) { + case 100: + case 133: + case 333: + return true; + default: + return false; + } +} + +/* + * Flesh out a simple rate table containing the high and low frequencies + * based on the current clock speed and the upper 32 bits of the MSR. + */ +status_t +est_msr_info(uint64 msr, freq_info **freqs) +{ + freq_info *fp; + int32 bus, freq, volts; + uint16 id; + + // Figure out the bus clock. + system_info sysInfo; + if (get_system_info(&sysInfo) != B_OK) + return B_ERROR; + + freq = sysInfo.cpu_clock_speed / 1000000; + id = msr >> 32; + bus = freq / (id >> 8); + + TRACE("est: Guessed bus clock (high) of %d MHz\n", int(bus)); + if (!bus_speed_ok(bus)) { + // We may be running on the low frequency. + id = msr >> 48; + bus = freq / (id >> 8); + TRACE("est: Guessed bus clock (low) of %d MHz\n", int(bus)); + if (!bus_speed_ok(bus)) + return B_ERROR; + + // Calculate high frequency. + id = msr >> 32; + freq = ((id >> 8) & 0xff) * bus; + } + + // Fill out a new freq table containing just the high and low freqs. + fp = (freq_info*)malloc(sizeof(freq_info) * 3); + memset(fp, 0, sizeof(freq_info) * 3); + + // First, the high frequency. + volts = id & 0xff; + if (volts != 0) { + volts <<= 4; + volts += 700; + } + fp[0].frequency = freq; + fp[0].volts = volts; + fp[0].id = id; + fp[0].power = CPUFREQ_VAL_UNKNOWN; + TRACE("Guessed high setting of %d MHz @ %d Mv\n", int(freq), int(volts)); + + // Second, the low frequency. + id = msr >> 48; + freq = ((id >> 8) & 0xff) * bus; + volts = id & 0xff; + if (volts != 0) { + volts <<= 4; + volts += 700; + } + fp[1].frequency = freq; + fp[1].volts = volts; + fp[1].id = id; + fp[1].power = CPUFREQ_VAL_UNKNOWN; + TRACE("Guessed low setting of %d MHz @ %d Mv\n", int(freq), int(volts)); + + // Table is already terminated due to M_ZERO. + *freqs = fp; + return B_OK; +} diff --git a/src/add-ons/kernel/drivers/power/enhanced_speedstep/frequency.h b/src/add-ons/kernel/drivers/power/enhanced_speedstep/frequency.h new file mode 100644 index 0000000000..454bc6e2bb --- /dev/null +++ b/src/add-ons/kernel/drivers/power/enhanced_speedstep/frequency.h @@ -0,0 +1,852 @@ +#ifndef FREQ_TABLE_H +#define FREQ_TABLE_H + +#include +#include +#include + +#include "device/power_managment.h" + +#define TRACE_EST +#ifdef TRACE_EST +# define TRACE(x...) dprintf(x) +#else +# define TRACE(x...) +#endif + +// this code is taken from freeBSD + +#define MSR_GET_FREQ_STATE 0x198 +#define MSR_SET_FREQ_STATE 0x199 + +/* Estimate in microseconds of latency for performing a transition. */ +#define EST_TRANS_LAT 1000 + +/* Identifying characteristics of a processor and supported frequencies. */ +typedef struct { + const uint32 vendor_id; + uint32 id32; + freq_info *freqtab; +} ss_cpu_info; + + +status_t est_get_info(freq_info **freqsInfo); +status_t est_table_info(uint64 msr, freq_info **freqs); +status_t est_msr_info(uint64 msr, freq_info **freqs); + +freq_info* est_get_current(freq_info *freq_list); +void est_get_id16(uint16 *id16_p); +status_t est_set_id16(uint16 id16, bool need_check = false); + +/* Convert MHz and mV into IDs for passing to the MSR. */ +#define ID16(MHz, mV, bus_clk) \ + (((MHz / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4)) +#define ID32(MHz_hi, mV_hi, MHz_lo, mV_lo, bus_clk) \ + ((ID16(MHz_lo, mV_lo, bus_clk) << 16) | (ID16(MHz_hi, mV_hi, bus_clk))) + +/* Format for storing IDs in our table. */ +#define CPUFREQ_VAL_UNKNOWN (-1) +#define CPU_VENDOR_INTEL B_CPU_INTEL_x86 +#define CPU_VENDOR_CENTAUR B_CPU_VIA_IDT_x86 + +#define FREQ_INFO_PWR(MHz, mV, bus_clk, mW) \ + { MHz, mV, ID16(MHz, mV, bus_clk), mW } +#define FREQ_INFO(MHz, mV, bus_clk) \ + FREQ_INFO_PWR(MHz, mV, bus_clk, CPUFREQ_VAL_UNKNOWN) +#define INTEL(tab, zhi, vhi, zlo, vlo, bus_clk) \ + { CPU_VENDOR_INTEL, ID32(zhi, vhi, zlo, vlo, bus_clk), tab } +#define CENTAUR(tab, zhi, vhi, zlo, vlo, bus_clk) \ + { CPU_VENDOR_CENTAUR, ID32(zhi, vhi, zlo, vlo, bus_clk), tab } + +/* Default bus clock value for Centrino processors. */ +#define INTEL_BUS_CLK 100 + +/* + * Frequency (MHz) and voltage (mV) settings. Data from the + * Intel Pentium M Processor Datasheet (Order Number 252612), Table 5. + * + * Dothan processors have multiple VID#s with different settings for + * each VID#. Since we can't uniquely identify this info + * without undisclosed methods from Intel, we can't support newer + * processors with this table method. If ACPI Px states are supported, + * we get info from them. + */ +static freq_info PM17_130[] = { + /* 130nm 1.70GHz Pentium M */ + FREQ_INFO(1700, 1484, INTEL_BUS_CLK), + FREQ_INFO(1400, 1308, INTEL_BUS_CLK), + FREQ_INFO(1200, 1228, INTEL_BUS_CLK), + FREQ_INFO(1000, 1116, INTEL_BUS_CLK), + FREQ_INFO( 800, 1004, INTEL_BUS_CLK), + FREQ_INFO( 600, 956, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM16_130[] = { + /* 130nm 1.60GHz Pentium M */ + FREQ_INFO(1600, 1484, INTEL_BUS_CLK), + FREQ_INFO(1400, 1420, INTEL_BUS_CLK), + FREQ_INFO(1200, 1276, INTEL_BUS_CLK), + FREQ_INFO(1000, 1164, INTEL_BUS_CLK), + FREQ_INFO( 800, 1036, INTEL_BUS_CLK), + FREQ_INFO( 600, 956, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM15_130[] = { + /* 130nm 1.50GHz Pentium M */ + FREQ_INFO(1500, 1484, INTEL_BUS_CLK), + FREQ_INFO(1400, 1452, INTEL_BUS_CLK), + FREQ_INFO(1200, 1356, INTEL_BUS_CLK), + FREQ_INFO(1000, 1228, INTEL_BUS_CLK), + FREQ_INFO( 800, 1116, INTEL_BUS_CLK), + FREQ_INFO( 600, 956, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM14_130[] = { + /* 130nm 1.40GHz Pentium M */ + FREQ_INFO(1400, 1484, INTEL_BUS_CLK), + FREQ_INFO(1200, 1436, INTEL_BUS_CLK), + FREQ_INFO(1000, 1308, INTEL_BUS_CLK), + FREQ_INFO( 800, 1180, INTEL_BUS_CLK), + FREQ_INFO( 600, 956, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM13_130[] = { + /* 130nm 1.30GHz Pentium M */ + FREQ_INFO(1300, 1388, INTEL_BUS_CLK), + FREQ_INFO(1200, 1356, INTEL_BUS_CLK), + FREQ_INFO(1000, 1292, INTEL_BUS_CLK), + FREQ_INFO( 800, 1260, INTEL_BUS_CLK), + FREQ_INFO( 600, 956, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM13_LV_130[] = { + /* 130nm 1.30GHz Low Voltage Pentium M */ + FREQ_INFO(1300, 1180, INTEL_BUS_CLK), + FREQ_INFO(1200, 1164, INTEL_BUS_CLK), + FREQ_INFO(1100, 1100, INTEL_BUS_CLK), + FREQ_INFO(1000, 1020, INTEL_BUS_CLK), + FREQ_INFO( 900, 1004, INTEL_BUS_CLK), + FREQ_INFO( 800, 988, INTEL_BUS_CLK), + FREQ_INFO( 600, 956, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM12_LV_130[] = { + /* 130 nm 1.20GHz Low Voltage Pentium M */ + FREQ_INFO(1200, 1180, INTEL_BUS_CLK), + FREQ_INFO(1100, 1164, INTEL_BUS_CLK), + FREQ_INFO(1000, 1100, INTEL_BUS_CLK), + FREQ_INFO( 900, 1020, INTEL_BUS_CLK), + FREQ_INFO( 800, 1004, INTEL_BUS_CLK), + FREQ_INFO( 600, 956, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM11_LV_130[] = { + /* 130 nm 1.10GHz Low Voltage Pentium M */ + FREQ_INFO(1100, 1180, INTEL_BUS_CLK), + FREQ_INFO(1000, 1164, INTEL_BUS_CLK), + FREQ_INFO( 900, 1100, INTEL_BUS_CLK), + FREQ_INFO( 800, 1020, INTEL_BUS_CLK), + FREQ_INFO( 600, 956, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM11_ULV_130[] = { + /* 130 nm 1.10GHz Ultra Low Voltage Pentium M */ + FREQ_INFO(1100, 1004, INTEL_BUS_CLK), + FREQ_INFO(1000, 988, INTEL_BUS_CLK), + FREQ_INFO( 900, 972, INTEL_BUS_CLK), + FREQ_INFO( 800, 956, INTEL_BUS_CLK), + FREQ_INFO( 600, 844, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM10_ULV_130[] = { + /* 130 nm 1.00GHz Ultra Low Voltage Pentium M */ + FREQ_INFO(1000, 1004, INTEL_BUS_CLK), + FREQ_INFO( 900, 988, INTEL_BUS_CLK), + FREQ_INFO( 800, 972, INTEL_BUS_CLK), + FREQ_INFO( 600, 844, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; + +/* + * Data from "Intel Pentium M Processor on 90nm Process with + * 2-MB L2 Cache Datasheet", Order Number 302189, Table 5. + */ +static freq_info PM_765A_90[] = { + /* 90 nm 2.10GHz Pentium M, VID #A */ + FREQ_INFO(2100, 1340, INTEL_BUS_CLK), + FREQ_INFO(1800, 1276, INTEL_BUS_CLK), + FREQ_INFO(1600, 1228, INTEL_BUS_CLK), + FREQ_INFO(1400, 1180, INTEL_BUS_CLK), + FREQ_INFO(1200, 1132, INTEL_BUS_CLK), + FREQ_INFO(1000, 1084, INTEL_BUS_CLK), + FREQ_INFO( 800, 1036, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_765B_90[] = { + /* 90 nm 2.10GHz Pentium M, VID #B */ + FREQ_INFO(2100, 1324, INTEL_BUS_CLK), + FREQ_INFO(1800, 1260, INTEL_BUS_CLK), + FREQ_INFO(1600, 1212, INTEL_BUS_CLK), + FREQ_INFO(1400, 1180, INTEL_BUS_CLK), + FREQ_INFO(1200, 1132, INTEL_BUS_CLK), + FREQ_INFO(1000, 1084, INTEL_BUS_CLK), + FREQ_INFO( 800, 1036, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_765C_90[] = { + /* 90 nm 2.10GHz Pentium M, VID #C */ + FREQ_INFO(2100, 1308, INTEL_BUS_CLK), + FREQ_INFO(1800, 1244, INTEL_BUS_CLK), + FREQ_INFO(1600, 1212, INTEL_BUS_CLK), + FREQ_INFO(1400, 1164, INTEL_BUS_CLK), + FREQ_INFO(1200, 1116, INTEL_BUS_CLK), + FREQ_INFO(1000, 1084, INTEL_BUS_CLK), + FREQ_INFO( 800, 1036, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_765E_90[] = { + /* 90 nm 2.10GHz Pentium M, VID #E */ + FREQ_INFO(2100, 1356, INTEL_BUS_CLK), + FREQ_INFO(1800, 1292, INTEL_BUS_CLK), + FREQ_INFO(1600, 1244, INTEL_BUS_CLK), + FREQ_INFO(1400, 1196, INTEL_BUS_CLK), + FREQ_INFO(1200, 1148, INTEL_BUS_CLK), + FREQ_INFO(1000, 1100, INTEL_BUS_CLK), + FREQ_INFO( 800, 1052, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_755A_90[] = { + /* 90 nm 2.00GHz Pentium M, VID #A */ + FREQ_INFO(2000, 1340, INTEL_BUS_CLK), + FREQ_INFO(1800, 1292, INTEL_BUS_CLK), + FREQ_INFO(1600, 1244, INTEL_BUS_CLK), + FREQ_INFO(1400, 1196, INTEL_BUS_CLK), + FREQ_INFO(1200, 1148, INTEL_BUS_CLK), + FREQ_INFO(1000, 1100, INTEL_BUS_CLK), + FREQ_INFO( 800, 1052, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_755B_90[] = { + /* 90 nm 2.00GHz Pentium M, VID #B */ + FREQ_INFO(2000, 1324, INTEL_BUS_CLK), + FREQ_INFO(1800, 1276, INTEL_BUS_CLK), + FREQ_INFO(1600, 1228, INTEL_BUS_CLK), + FREQ_INFO(1400, 1180, INTEL_BUS_CLK), + FREQ_INFO(1200, 1132, INTEL_BUS_CLK), + FREQ_INFO(1000, 1084, INTEL_BUS_CLK), + FREQ_INFO( 800, 1036, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_755C_90[] = { + /* 90 nm 2.00GHz Pentium M, VID #C */ + FREQ_INFO(2000, 1308, INTEL_BUS_CLK), + FREQ_INFO(1800, 1276, INTEL_BUS_CLK), + FREQ_INFO(1600, 1228, INTEL_BUS_CLK), + FREQ_INFO(1400, 1180, INTEL_BUS_CLK), + FREQ_INFO(1200, 1132, INTEL_BUS_CLK), + FREQ_INFO(1000, 1084, INTEL_BUS_CLK), + FREQ_INFO( 800, 1036, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_755D_90[] = { + /* 90 nm 2.00GHz Pentium M, VID #D */ + FREQ_INFO(2000, 1276, INTEL_BUS_CLK), + FREQ_INFO(1800, 1244, INTEL_BUS_CLK), + FREQ_INFO(1600, 1196, INTEL_BUS_CLK), + FREQ_INFO(1400, 1164, INTEL_BUS_CLK), + FREQ_INFO(1200, 1116, INTEL_BUS_CLK), + FREQ_INFO(1000, 1084, INTEL_BUS_CLK), + FREQ_INFO( 800, 1036, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_745A_90[] = { + /* 90 nm 1.80GHz Pentium M, VID #A */ + FREQ_INFO(1800, 1340, INTEL_BUS_CLK), + FREQ_INFO(1600, 1292, INTEL_BUS_CLK), + FREQ_INFO(1400, 1228, INTEL_BUS_CLK), + FREQ_INFO(1200, 1164, INTEL_BUS_CLK), + FREQ_INFO(1000, 1116, INTEL_BUS_CLK), + FREQ_INFO( 800, 1052, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_745B_90[] = { + /* 90 nm 1.80GHz Pentium M, VID #B */ + FREQ_INFO(1800, 1324, INTEL_BUS_CLK), + FREQ_INFO(1600, 1276, INTEL_BUS_CLK), + FREQ_INFO(1400, 1212, INTEL_BUS_CLK), + FREQ_INFO(1200, 1164, INTEL_BUS_CLK), + FREQ_INFO(1000, 1116, INTEL_BUS_CLK), + FREQ_INFO( 800, 1052, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_745C_90[] = { + /* 90 nm 1.80GHz Pentium M, VID #C */ + FREQ_INFO(1800, 1308, INTEL_BUS_CLK), + FREQ_INFO(1600, 1260, INTEL_BUS_CLK), + FREQ_INFO(1400, 1212, INTEL_BUS_CLK), + FREQ_INFO(1200, 1148, INTEL_BUS_CLK), + FREQ_INFO(1000, 1100, INTEL_BUS_CLK), + FREQ_INFO( 800, 1052, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_745D_90[] = { + /* 90 nm 1.80GHz Pentium M, VID #D */ + FREQ_INFO(1800, 1276, INTEL_BUS_CLK), + FREQ_INFO(1600, 1228, INTEL_BUS_CLK), + FREQ_INFO(1400, 1180, INTEL_BUS_CLK), + FREQ_INFO(1200, 1132, INTEL_BUS_CLK), + FREQ_INFO(1000, 1084, INTEL_BUS_CLK), + FREQ_INFO( 800, 1036, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_735A_90[] = { + /* 90 nm 1.70GHz Pentium M, VID #A */ + FREQ_INFO(1700, 1340, INTEL_BUS_CLK), + FREQ_INFO(1400, 1244, INTEL_BUS_CLK), + FREQ_INFO(1200, 1180, INTEL_BUS_CLK), + FREQ_INFO(1000, 1116, INTEL_BUS_CLK), + FREQ_INFO( 800, 1052, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_735B_90[] = { + /* 90 nm 1.70GHz Pentium M, VID #B */ + FREQ_INFO(1700, 1324, INTEL_BUS_CLK), + FREQ_INFO(1400, 1244, INTEL_BUS_CLK), + FREQ_INFO(1200, 1180, INTEL_BUS_CLK), + FREQ_INFO(1000, 1116, INTEL_BUS_CLK), + FREQ_INFO( 800, 1052, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_735C_90[] = { + /* 90 nm 1.70GHz Pentium M, VID #C */ + FREQ_INFO(1700, 1308, INTEL_BUS_CLK), + FREQ_INFO(1400, 1228, INTEL_BUS_CLK), + FREQ_INFO(1200, 1164, INTEL_BUS_CLK), + FREQ_INFO(1000, 1116, INTEL_BUS_CLK), + FREQ_INFO( 800, 1052, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_735D_90[] = { + /* 90 nm 1.70GHz Pentium M, VID #D */ + FREQ_INFO(1700, 1276, INTEL_BUS_CLK), + FREQ_INFO(1400, 1212, INTEL_BUS_CLK), + FREQ_INFO(1200, 1148, INTEL_BUS_CLK), + FREQ_INFO(1000, 1100, INTEL_BUS_CLK), + FREQ_INFO( 800, 1052, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_725A_90[] = { + /* 90 nm 1.60GHz Pentium M, VID #A */ + FREQ_INFO(1600, 1340, INTEL_BUS_CLK), + FREQ_INFO(1400, 1276, INTEL_BUS_CLK), + FREQ_INFO(1200, 1212, INTEL_BUS_CLK), + FREQ_INFO(1000, 1132, INTEL_BUS_CLK), + FREQ_INFO( 800, 1068, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_725B_90[] = { + /* 90 nm 1.60GHz Pentium M, VID #B */ + FREQ_INFO(1600, 1324, INTEL_BUS_CLK), + FREQ_INFO(1400, 1260, INTEL_BUS_CLK), + FREQ_INFO(1200, 1196, INTEL_BUS_CLK), + FREQ_INFO(1000, 1132, INTEL_BUS_CLK), + FREQ_INFO( 800, 1068, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_725C_90[] = { + /* 90 nm 1.60GHz Pentium M, VID #C */ + FREQ_INFO(1600, 1308, INTEL_BUS_CLK), + FREQ_INFO(1400, 1244, INTEL_BUS_CLK), + FREQ_INFO(1200, 1180, INTEL_BUS_CLK), + FREQ_INFO(1000, 1116, INTEL_BUS_CLK), + FREQ_INFO( 800, 1052, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_725D_90[] = { + /* 90 nm 1.60GHz Pentium M, VID #D */ + FREQ_INFO(1600, 1276, INTEL_BUS_CLK), + FREQ_INFO(1400, 1228, INTEL_BUS_CLK), + FREQ_INFO(1200, 1164, INTEL_BUS_CLK), + FREQ_INFO(1000, 1116, INTEL_BUS_CLK), + FREQ_INFO( 800, 1052, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_715A_90[] = { + /* 90 nm 1.50GHz Pentium M, VID #A */ + FREQ_INFO(1500, 1340, INTEL_BUS_CLK), + FREQ_INFO(1200, 1228, INTEL_BUS_CLK), + FREQ_INFO(1000, 1148, INTEL_BUS_CLK), + FREQ_INFO( 800, 1068, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_715B_90[] = { + /* 90 nm 1.50GHz Pentium M, VID #B */ + FREQ_INFO(1500, 1324, INTEL_BUS_CLK), + FREQ_INFO(1200, 1212, INTEL_BUS_CLK), + FREQ_INFO(1000, 1148, INTEL_BUS_CLK), + FREQ_INFO( 800, 1068, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_715C_90[] = { + /* 90 nm 1.50GHz Pentium M, VID #C */ + FREQ_INFO(1500, 1308, INTEL_BUS_CLK), + FREQ_INFO(1200, 1212, INTEL_BUS_CLK), + FREQ_INFO(1000, 1132, INTEL_BUS_CLK), + FREQ_INFO( 800, 1068, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_715D_90[] = { + /* 90 nm 1.50GHz Pentium M, VID #D */ + FREQ_INFO(1500, 1276, INTEL_BUS_CLK), + FREQ_INFO(1200, 1180, INTEL_BUS_CLK), + FREQ_INFO(1000, 1116, INTEL_BUS_CLK), + FREQ_INFO( 800, 1052, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_778_90[] = { + /* 90 nm 1.60GHz Low Voltage Pentium M */ + FREQ_INFO(1600, 1116, INTEL_BUS_CLK), + FREQ_INFO(1500, 1116, INTEL_BUS_CLK), + FREQ_INFO(1400, 1100, INTEL_BUS_CLK), + FREQ_INFO(1300, 1084, INTEL_BUS_CLK), + FREQ_INFO(1200, 1068, INTEL_BUS_CLK), + FREQ_INFO(1100, 1052, INTEL_BUS_CLK), + FREQ_INFO(1000, 1052, INTEL_BUS_CLK), + FREQ_INFO( 900, 1036, INTEL_BUS_CLK), + FREQ_INFO( 800, 1020, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_758_90[] = { + /* 90 nm 1.50GHz Low Voltage Pentium M */ + FREQ_INFO(1500, 1116, INTEL_BUS_CLK), + FREQ_INFO(1400, 1116, INTEL_BUS_CLK), + FREQ_INFO(1300, 1100, INTEL_BUS_CLK), + FREQ_INFO(1200, 1084, INTEL_BUS_CLK), + FREQ_INFO(1100, 1068, INTEL_BUS_CLK), + FREQ_INFO(1000, 1052, INTEL_BUS_CLK), + FREQ_INFO( 900, 1036, INTEL_BUS_CLK), + FREQ_INFO( 800, 1020, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_738_90[] = { + /* 90 nm 1.40GHz Low Voltage Pentium M */ + FREQ_INFO(1400, 1116, INTEL_BUS_CLK), + FREQ_INFO(1300, 1116, INTEL_BUS_CLK), + FREQ_INFO(1200, 1100, INTEL_BUS_CLK), + FREQ_INFO(1100, 1068, INTEL_BUS_CLK), + FREQ_INFO(1000, 1052, INTEL_BUS_CLK), + FREQ_INFO( 900, 1036, INTEL_BUS_CLK), + FREQ_INFO( 800, 1020, INTEL_BUS_CLK), + FREQ_INFO( 600, 988, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_773G_90[] = { + /* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #G */ + FREQ_INFO(1300, 956, INTEL_BUS_CLK), + FREQ_INFO(1200, 940, INTEL_BUS_CLK), + FREQ_INFO(1100, 924, INTEL_BUS_CLK), + FREQ_INFO(1000, 908, INTEL_BUS_CLK), + FREQ_INFO( 900, 876, INTEL_BUS_CLK), + FREQ_INFO( 800, 860, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_773H_90[] = { + /* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #H */ + FREQ_INFO(1300, 940, INTEL_BUS_CLK), + FREQ_INFO(1200, 924, INTEL_BUS_CLK), + FREQ_INFO(1100, 908, INTEL_BUS_CLK), + FREQ_INFO(1000, 892, INTEL_BUS_CLK), + FREQ_INFO( 900, 876, INTEL_BUS_CLK), + FREQ_INFO( 800, 860, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_773I_90[] = { + /* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #I */ + FREQ_INFO(1300, 924, INTEL_BUS_CLK), + FREQ_INFO(1200, 908, INTEL_BUS_CLK), + FREQ_INFO(1100, 892, INTEL_BUS_CLK), + FREQ_INFO(1000, 876, INTEL_BUS_CLK), + FREQ_INFO( 900, 860, INTEL_BUS_CLK), + FREQ_INFO( 800, 844, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_773J_90[] = { + /* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #J */ + FREQ_INFO(1300, 908, INTEL_BUS_CLK), + FREQ_INFO(1200, 908, INTEL_BUS_CLK), + FREQ_INFO(1100, 892, INTEL_BUS_CLK), + FREQ_INFO(1000, 876, INTEL_BUS_CLK), + FREQ_INFO( 900, 860, INTEL_BUS_CLK), + FREQ_INFO( 800, 844, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_773K_90[] = { + /* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #K */ + FREQ_INFO(1300, 892, INTEL_BUS_CLK), + FREQ_INFO(1200, 892, INTEL_BUS_CLK), + FREQ_INFO(1100, 876, INTEL_BUS_CLK), + FREQ_INFO(1000, 860, INTEL_BUS_CLK), + FREQ_INFO( 900, 860, INTEL_BUS_CLK), + FREQ_INFO( 800, 844, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_773L_90[] = { + /* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #L */ + FREQ_INFO(1300, 876, INTEL_BUS_CLK), + FREQ_INFO(1200, 876, INTEL_BUS_CLK), + FREQ_INFO(1100, 860, INTEL_BUS_CLK), + FREQ_INFO(1000, 860, INTEL_BUS_CLK), + FREQ_INFO( 900, 844, INTEL_BUS_CLK), + FREQ_INFO( 800, 844, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_753G_90[] = { + /* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #G */ + FREQ_INFO(1200, 956, INTEL_BUS_CLK), + FREQ_INFO(1100, 940, INTEL_BUS_CLK), + FREQ_INFO(1000, 908, INTEL_BUS_CLK), + FREQ_INFO( 900, 892, INTEL_BUS_CLK), + FREQ_INFO( 800, 860, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_753H_90[] = { + /* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #H */ + FREQ_INFO(1200, 940, INTEL_BUS_CLK), + FREQ_INFO(1100, 924, INTEL_BUS_CLK), + FREQ_INFO(1000, 908, INTEL_BUS_CLK), + FREQ_INFO( 900, 876, INTEL_BUS_CLK), + FREQ_INFO( 800, 860, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_753I_90[] = { + /* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #I */ + FREQ_INFO(1200, 924, INTEL_BUS_CLK), + FREQ_INFO(1100, 908, INTEL_BUS_CLK), + FREQ_INFO(1000, 892, INTEL_BUS_CLK), + FREQ_INFO( 900, 876, INTEL_BUS_CLK), + FREQ_INFO( 800, 860, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_753J_90[] = { + /* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #J */ + FREQ_INFO(1200, 908, INTEL_BUS_CLK), + FREQ_INFO(1100, 892, INTEL_BUS_CLK), + FREQ_INFO(1000, 876, INTEL_BUS_CLK), + FREQ_INFO( 900, 860, INTEL_BUS_CLK), + FREQ_INFO( 800, 844, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_753K_90[] = { + /* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #K */ + FREQ_INFO(1200, 892, INTEL_BUS_CLK), + FREQ_INFO(1100, 892, INTEL_BUS_CLK), + FREQ_INFO(1000, 876, INTEL_BUS_CLK), + FREQ_INFO( 900, 860, INTEL_BUS_CLK), + FREQ_INFO( 800, 844, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_753L_90[] = { + /* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #L */ + FREQ_INFO(1200, 876, INTEL_BUS_CLK), + FREQ_INFO(1100, 876, INTEL_BUS_CLK), + FREQ_INFO(1000, 860, INTEL_BUS_CLK), + FREQ_INFO( 900, 844, INTEL_BUS_CLK), + FREQ_INFO( 800, 844, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; + +static freq_info PM_733JG_90[] = { + /* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #G */ + FREQ_INFO(1100, 956, INTEL_BUS_CLK), + FREQ_INFO(1000, 940, INTEL_BUS_CLK), + FREQ_INFO( 900, 908, INTEL_BUS_CLK), + FREQ_INFO( 800, 876, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_733JH_90[] = { + /* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #H */ + FREQ_INFO(1100, 940, INTEL_BUS_CLK), + FREQ_INFO(1000, 924, INTEL_BUS_CLK), + FREQ_INFO( 900, 892, INTEL_BUS_CLK), + FREQ_INFO( 800, 876, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_733JI_90[] = { + /* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #I */ + FREQ_INFO(1100, 924, INTEL_BUS_CLK), + FREQ_INFO(1000, 908, INTEL_BUS_CLK), + FREQ_INFO( 900, 892, INTEL_BUS_CLK), + FREQ_INFO( 800, 860, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_733JJ_90[] = { + /* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #J */ + FREQ_INFO(1100, 908, INTEL_BUS_CLK), + FREQ_INFO(1000, 892, INTEL_BUS_CLK), + FREQ_INFO( 900, 876, INTEL_BUS_CLK), + FREQ_INFO( 800, 860, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_733JK_90[] = { + /* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #K */ + FREQ_INFO(1100, 892, INTEL_BUS_CLK), + FREQ_INFO(1000, 876, INTEL_BUS_CLK), + FREQ_INFO( 900, 860, INTEL_BUS_CLK), + FREQ_INFO( 800, 844, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_733JL_90[] = { + /* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #L */ + FREQ_INFO(1100, 876, INTEL_BUS_CLK), + FREQ_INFO(1000, 876, INTEL_BUS_CLK), + FREQ_INFO( 900, 860, INTEL_BUS_CLK), + FREQ_INFO( 800, 844, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), +}; +static freq_info PM_733_90[] = { + /* 90 nm 1.10GHz Ultra Low Voltage Pentium M */ + FREQ_INFO(1100, 940, INTEL_BUS_CLK), + FREQ_INFO(1000, 924, INTEL_BUS_CLK), + FREQ_INFO( 900, 892, INTEL_BUS_CLK), + FREQ_INFO( 800, 876, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; +static freq_info PM_723_90[] = { + /* 90 nm 1.00GHz Ultra Low Voltage Pentium M */ + FREQ_INFO(1000, 940, INTEL_BUS_CLK), + FREQ_INFO( 900, 908, INTEL_BUS_CLK), + FREQ_INFO( 800, 876, INTEL_BUS_CLK), + FREQ_INFO( 600, 812, INTEL_BUS_CLK), + FREQ_INFO( 0, 0, 1), +}; + +/* + * VIA C7-M 500 MHz FSB, 400 MHz FSB, and ULV variants. + * Data from the "VIA C7-M Processor BIOS Writer's Guide (v2.17)" datasheet. + */ +static freq_info C7M_795[] = { + /* 2.00GHz Centaur C7-M 533 Mhz FSB */ + FREQ_INFO_PWR(2000, 1148, 133, 20000), + FREQ_INFO_PWR(1867, 1132, 133, 18000), + FREQ_INFO_PWR(1600, 1100, 133, 15000), + FREQ_INFO_PWR(1467, 1052, 133, 13000), + FREQ_INFO_PWR(1200, 1004, 133, 10000), + FREQ_INFO_PWR( 800, 844, 133, 7000), + FREQ_INFO_PWR( 667, 844, 133, 6000), + FREQ_INFO_PWR( 533, 844, 133, 5000), + FREQ_INFO(0, 0, 1), +}; +static freq_info C7M_785[] = { + /* 1.80GHz Centaur C7-M 533 Mhz FSB */ + FREQ_INFO_PWR(1867, 1148, 133, 18000), + FREQ_INFO_PWR(1600, 1100, 133, 15000), + FREQ_INFO_PWR(1467, 1052, 133, 13000), + FREQ_INFO_PWR(1200, 1004, 133, 10000), + FREQ_INFO_PWR( 800, 844, 133, 7000), + FREQ_INFO_PWR( 667, 844, 133, 6000), + FREQ_INFO_PWR( 533, 844, 133, 5000), + FREQ_INFO(0, 0, 1), +}; +static freq_info C7M_765[] = { + /* 1.60GHz Centaur C7-M 533 Mhz FSB */ + FREQ_INFO_PWR(1600, 1084, 133, 15000), + FREQ_INFO_PWR(1467, 1052, 133, 13000), + FREQ_INFO_PWR(1200, 1004, 133, 10000), + FREQ_INFO_PWR( 800, 844, 133, 7000), + FREQ_INFO_PWR( 667, 844, 133, 6000), + FREQ_INFO_PWR( 533, 844, 133, 5000), + FREQ_INFO(0, 0, 1), +}; + +static freq_info C7M_794[] = { + /* 2.00GHz Centaur C7-M 400 Mhz FSB */ + FREQ_INFO_PWR(2000, 1148, 100, 20000), + FREQ_INFO_PWR(1800, 1132, 100, 18000), + FREQ_INFO_PWR(1600, 1100, 100, 15000), + FREQ_INFO_PWR(1400, 1052, 100, 13000), + FREQ_INFO_PWR(1000, 1004, 100, 10000), + FREQ_INFO_PWR( 800, 844, 100, 7000), + FREQ_INFO_PWR( 600, 844, 100, 6000), + FREQ_INFO_PWR( 400, 844, 100, 5000), + FREQ_INFO(0, 0, 1), +}; +static freq_info C7M_784[] = { + /* 1.80GHz Centaur C7-M 400 Mhz FSB */ + FREQ_INFO_PWR(1800, 1148, 100, 18000), + FREQ_INFO_PWR(1600, 1100, 100, 15000), + FREQ_INFO_PWR(1400, 1052, 100, 13000), + FREQ_INFO_PWR(1000, 1004, 100, 10000), + FREQ_INFO_PWR( 800, 844, 100, 7000), + FREQ_INFO_PWR( 600, 844, 100, 6000), + FREQ_INFO_PWR( 400, 844, 100, 5000), + FREQ_INFO(0, 0, 1), +}; +static freq_info C7M_764[] = { + /* 1.60GHz Centaur C7-M 400 Mhz FSB */ + FREQ_INFO_PWR(1600, 1084, 100, 15000), + FREQ_INFO_PWR(1400, 1052, 100, 13000), + FREQ_INFO_PWR(1000, 1004, 100, 10000), + FREQ_INFO_PWR( 800, 844, 100, 7000), + FREQ_INFO_PWR( 600, 844, 100, 6000), + FREQ_INFO_PWR( 400, 844, 100, 5000), + FREQ_INFO(0, 0, 1), +}; +static freq_info C7M_754[] = { + /* 1.50GHz Centaur C7-M 400 Mhz FSB */ + FREQ_INFO_PWR(1500, 1004, 100, 12000), + FREQ_INFO_PWR(1400, 988, 100, 11000), + FREQ_INFO_PWR(1000, 940, 100, 9000), + FREQ_INFO_PWR( 800, 844, 100, 7000), + FREQ_INFO_PWR( 600, 844, 100, 6000), + FREQ_INFO_PWR( 400, 844, 100, 5000), + FREQ_INFO(0, 0, 1), +}; +static freq_info C7M_771[] = { + /* 1.20GHz Centaur C7-M 400 Mhz FSB */ + FREQ_INFO_PWR(1200, 860, 100, 7000), + FREQ_INFO_PWR(1000, 860, 100, 6000), + FREQ_INFO_PWR( 800, 844, 100, 5500), + FREQ_INFO_PWR( 600, 844, 100, 5000), + FREQ_INFO_PWR( 400, 844, 100, 4000), + FREQ_INFO(0, 0, 1), +}; + +static freq_info C7M_775_ULV[] = { + /* 1.50GHz Centaur C7-M ULV */ + FREQ_INFO_PWR(1500, 956, 100, 7500), + FREQ_INFO_PWR(1400, 940, 100, 6000), + FREQ_INFO_PWR(1000, 860, 100, 5000), + FREQ_INFO_PWR( 800, 828, 100, 2800), + FREQ_INFO_PWR( 600, 796, 100, 2500), + FREQ_INFO_PWR( 400, 796, 100, 2000), + FREQ_INFO(0, 0, 1), +}; +static freq_info C7M_772_ULV[] = { + /* 1.20GHz Centaur C7-M ULV */ + FREQ_INFO_PWR(1200, 844, 100, 5000), + FREQ_INFO_PWR(1000, 844, 100, 4000), + FREQ_INFO_PWR( 800, 828, 100, 2800), + FREQ_INFO_PWR( 600, 796, 100, 2500), + FREQ_INFO_PWR( 400, 796, 100, 2000), + FREQ_INFO(0, 0, 1), +}; +static freq_info C7M_779_ULV[] = { + /* 1.00GHz Centaur C7-M ULV */ + FREQ_INFO_PWR(1000, 796, 100, 3500), + FREQ_INFO_PWR( 800, 796, 100, 2800), + FREQ_INFO_PWR( 600, 796, 100, 2500), + FREQ_INFO_PWR( 400, 796, 100, 2000), + FREQ_INFO(0, 0, 1), +}; +static freq_info C7M_770_ULV[] = { + /* 1.00GHz Centaur C7-M ULV */ + FREQ_INFO_PWR(1000, 844, 100, 5000), + FREQ_INFO_PWR( 800, 796, 100, 2800), + FREQ_INFO_PWR( 600, 796, 100, 2500), + FREQ_INFO_PWR( 400, 796, 100, 2000), + FREQ_INFO(0, 0, 1), +}; + +static ss_cpu_info ESTprocs[] = { + INTEL(PM17_130, 1700, 1484, 600, 956, INTEL_BUS_CLK), + INTEL(PM16_130, 1600, 1484, 600, 956, INTEL_BUS_CLK), + INTEL(PM15_130, 1500, 1484, 600, 956, INTEL_BUS_CLK), + INTEL(PM14_130, 1400, 1484, 600, 956, INTEL_BUS_CLK), + INTEL(PM13_130, 1300, 1388, 600, 956, INTEL_BUS_CLK), + INTEL(PM13_LV_130, 1300, 1180, 600, 956, INTEL_BUS_CLK), + INTEL(PM12_LV_130, 1200, 1180, 600, 956, INTEL_BUS_CLK), + INTEL(PM11_LV_130, 1100, 1180, 600, 956, INTEL_BUS_CLK), + INTEL(PM11_ULV_130, 1100, 1004, 600, 844, INTEL_BUS_CLK), + INTEL(PM10_ULV_130, 1000, 1004, 600, 844, INTEL_BUS_CLK), + INTEL(PM_765A_90, 2100, 1340, 600, 988, INTEL_BUS_CLK), + INTEL(PM_765B_90, 2100, 1324, 600, 988, INTEL_BUS_CLK), + INTEL(PM_765C_90, 2100, 1308, 600, 988, INTEL_BUS_CLK), + INTEL(PM_765E_90, 2100, 1356, 600, 988, INTEL_BUS_CLK), + INTEL(PM_755A_90, 2000, 1340, 600, 988, INTEL_BUS_CLK), + INTEL(PM_755B_90, 2000, 1324, 600, 988, INTEL_BUS_CLK), + INTEL(PM_755C_90, 2000, 1308, 600, 988, INTEL_BUS_CLK), + INTEL(PM_755D_90, 2000, 1276, 600, 988, INTEL_BUS_CLK), + INTEL(PM_745A_90, 1800, 1340, 600, 988, INTEL_BUS_CLK), + INTEL(PM_745B_90, 1800, 1324, 600, 988, INTEL_BUS_CLK), + INTEL(PM_745C_90, 1800, 1308, 600, 988, INTEL_BUS_CLK), + INTEL(PM_745D_90, 1800, 1276, 600, 988, INTEL_BUS_CLK), + INTEL(PM_735A_90, 1700, 1340, 600, 988, INTEL_BUS_CLK), + INTEL(PM_735B_90, 1700, 1324, 600, 988, INTEL_BUS_CLK), + INTEL(PM_735C_90, 1700, 1308, 600, 988, INTEL_BUS_CLK), + INTEL(PM_735D_90, 1700, 1276, 600, 988, INTEL_BUS_CLK), + INTEL(PM_725A_90, 1600, 1340, 600, 988, INTEL_BUS_CLK), + INTEL(PM_725B_90, 1600, 1324, 600, 988, INTEL_BUS_CLK), + INTEL(PM_725C_90, 1600, 1308, 600, 988, INTEL_BUS_CLK), + INTEL(PM_725D_90, 1600, 1276, 600, 988, INTEL_BUS_CLK), + INTEL(PM_715A_90, 1500, 1340, 600, 988, INTEL_BUS_CLK), + INTEL(PM_715B_90, 1500, 1324, 600, 988, INTEL_BUS_CLK), + INTEL(PM_715C_90, 1500, 1308, 600, 988, INTEL_BUS_CLK), + INTEL(PM_715D_90, 1500, 1276, 600, 988, INTEL_BUS_CLK), + INTEL(PM_778_90, 1600, 1116, 600, 988, INTEL_BUS_CLK), + INTEL(PM_758_90, 1500, 1116, 600, 988, INTEL_BUS_CLK), + INTEL(PM_738_90, 1400, 1116, 600, 988, INTEL_BUS_CLK), + INTEL(PM_773G_90, 1300, 956, 600, 812, INTEL_BUS_CLK), + INTEL(PM_773H_90, 1300, 940, 600, 812, INTEL_BUS_CLK), + INTEL(PM_773I_90, 1300, 924, 600, 812, INTEL_BUS_CLK), + INTEL(PM_773J_90, 1300, 908, 600, 812, INTEL_BUS_CLK), + INTEL(PM_773K_90, 1300, 892, 600, 812, INTEL_BUS_CLK), + INTEL(PM_773L_90, 1300, 876, 600, 812, INTEL_BUS_CLK), + INTEL(PM_753G_90, 1200, 956, 600, 812, INTEL_BUS_CLK), + INTEL(PM_753H_90, 1200, 940, 600, 812, INTEL_BUS_CLK), + INTEL(PM_753I_90, 1200, 924, 600, 812, INTEL_BUS_CLK), + INTEL(PM_753J_90, 1200, 908, 600, 812, INTEL_BUS_CLK), + INTEL(PM_753K_90, 1200, 892, 600, 812, INTEL_BUS_CLK), + INTEL(PM_753L_90, 1200, 876, 600, 812, INTEL_BUS_CLK), + INTEL(PM_733JG_90, 1100, 956, 600, 812, INTEL_BUS_CLK), + INTEL(PM_733JH_90, 1100, 940, 600, 812, INTEL_BUS_CLK), + INTEL(PM_733JI_90, 1100, 924, 600, 812, INTEL_BUS_CLK), + INTEL(PM_733JJ_90, 1100, 908, 600, 812, INTEL_BUS_CLK), + INTEL(PM_733JK_90, 1100, 892, 600, 812, INTEL_BUS_CLK), + INTEL(PM_733JL_90, 1100, 876, 600, 812, INTEL_BUS_CLK), + INTEL(PM_733_90, 1100, 940, 600, 812, INTEL_BUS_CLK), + INTEL(PM_723_90, 1000, 940, 600, 812, INTEL_BUS_CLK), + + CENTAUR(C7M_795, 2000, 1148, 533, 844, 133), + CENTAUR(C7M_794, 2000, 1148, 400, 844, 100), + CENTAUR(C7M_785, 1867, 1148, 533, 844, 133), + CENTAUR(C7M_784, 1800, 1148, 400, 844, 100), + CENTAUR(C7M_765, 1600, 1084, 533, 844, 133), + CENTAUR(C7M_764, 1600, 1084, 400, 844, 100), + CENTAUR(C7M_754, 1500, 1004, 400, 844, 100), + CENTAUR(C7M_775_ULV, 1500, 956, 400, 796, 100), + CENTAUR(C7M_771, 1200, 860, 400, 844, 100), + CENTAUR(C7M_772_ULV, 1200, 844, 400, 796, 100), + CENTAUR(C7M_779_ULV, 1000, 796, 400, 796, 100), + CENTAUR(C7M_770_ULV, 1000, 844, 400, 796, 100), + { 0, 0, NULL }, +}; + +#endif + diff --git a/src/preferences/Jamfile b/src/preferences/Jamfile index 62e5e31912..7389c29f2b 100644 --- a/src/preferences/Jamfile +++ b/src/preferences/Jamfile @@ -2,6 +2,7 @@ SubDir HAIKU_TOP src preferences ; SubInclude HAIKU_TOP src preferences appearance ; SubInclude HAIKU_TOP src preferences backgrounds ; +SubInclude HAIKU_TOP src preferences cpufrequency ; SubInclude HAIKU_TOP src preferences datatranslations ; SubInclude HAIKU_TOP src preferences devices ; #SubInclude HAIKU_TOP src preferences dun ; diff --git a/src/preferences/cpufrequency/CPUFrequencyView.cpp b/src/preferences/cpufrequency/CPUFrequencyView.cpp new file mode 100644 index 0000000000..3a5e62ea16 --- /dev/null +++ b/src/preferences/cpufrequency/CPUFrequencyView.cpp @@ -0,0 +1,243 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#include "CPUFrequencyView.h" + +#include "StatusView.h" + +#include +#include +#include +#include +#include + +const char* kCPUFreqPreferencesFile = "CPUFrequency"; +const char* kPrefSignature = "application/x-vnd.Haiku-CPUFrequencyPref"; +const char* kPreferencesFileName = "CPUFrequency"; + +const uint32 kInstallIntoDeskbar = '&iid'; +const uint32 kIntegrationTimeChanged = '&itc'; + +const bigtime_t kMilliSecond = 1000; + + +CPUFrequencyView::CPUFrequencyView(BRect frame, + PreferencesStorage* storage) + : BView(frame, "CPUFrequencyView", B_FOLLOW_NONE, B_WILL_DRAW), + fStorage(storage) +{ + BGroupLayout* mainLayout = new BGroupLayout(B_VERTICAL); + SetLayout(mainLayout); + mainLayout->SetSpacing(10); + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + // stepping policy + BRect rect = Bounds(); + rect.InsetBy(5, 5); + BBox *policyBox = new BBox(rect, "policyBox"); + policyBox->SetLabel("Stepping Policy"); + BGroupLayout* policyLayout = new BGroupLayout(B_VERTICAL); + policyLayout->SetInsets(10, policyBox->TopBorderOffset() * 2 + 10, 10, 10); + policyLayout->SetSpacing(10); + policyBox->SetLayout(policyLayout); + mainLayout->AddView(policyBox); + + fPolicyMenu = new BMenu("Stepping Policy"); + BMenuField *menuField = new BMenuField("Stepping Policy", fPolicyMenu); + + policyLayout->AddView(menuField); + + // dynamic stepping + BBox *dynamicBox = new BBox(rect, "dynamicBox"); + dynamicBox->SetLabel("Dynamic Stepping"); + BGroupLayout* dynamicLayout = new BGroupLayout(B_VERTICAL); + dynamicLayout->SetInsets(10, dynamicBox->TopBorderOffset() * 2 + 10, + 10, 10); + dynamicLayout->SetSpacing(10); + dynamicBox->SetLayout(dynamicLayout); + mainLayout->AddView(dynamicBox); + + fColorStepView = new ColorStepView(frame); + fColorStepView->SetFrequencys(fDriverInterface.GetCpuFrequencyStates()); + + fIntegrationTime = new BTextControl(BRect(0,0,Bounds().Width(),10), + "intergal", + "Integration Time [ms]", "", + new BMessage(kIntegrationTimeChanged)); + + dynamicLayout->AddView(fColorStepView); + dynamicLayout->AddView(fIntegrationTime); + + // status view + BBox *statusBox = new BBox(rect, "statusBox"); + statusBox->SetLabel("CPU Frequency Status View"); + BGroupLayout* statusLayout = new BGroupLayout(B_HORIZONTAL); + statusLayout->SetInsets(10, statusBox->TopBorderOffset() * 2 + 10, 10, 10); + statusLayout->SetSpacing(10); + statusBox->SetLayout(statusLayout); + mainLayout->AddView(statusBox); + + fStatusView = new StatusView(BRect(0, 0, 5, 5), false, + fStorage); + fStatusView->ShowPopUpMenu(false); + + fInstallButton = new BButton("installButton", + "Install Replicant into Deskbar", + new BMessage(kInstallIntoDeskbar)); + + statusLayout->AddView(fStatusView); + statusLayout->AddView(fInstallButton); + statusLayout->AddItem(BSpaceLayoutItem::CreateGlue()); +} + + +void +CPUFrequencyView::MessageReceived(BMessage* message) +{ + freq_preferences* pref = fStorage->GetPreferences(); + bool configChanged = false; + + switch (message->what) { + case kUpdatedPreferences: + fStatusView->MessageReceived(message); + if (pref->mode == DYNAMIC) { + fColorStepView->SetEnabled(true); + fIntegrationTime->SetEnabled(true); + } + else { + fColorStepView->SetEnabled(false); + fIntegrationTime->SetEnabled(false); + } + configChanged = true; + break; + + case kSteppingChanged: + // from ColorStepView + pref->stepping_threshold = fColorStepView->GetSliderPosition(); + fStorage->SavePreferences(); + configChanged = true; + break; + + case kIntegrationTimeChanged: + _ReadIntegrationTime(); + fStorage->SavePreferences(); + configChanged = true; + break; + + case kInstallIntoDeskbar: + _InstallReplicantInDeskbar(); + break; + + case kRevertMsg: + case kDefaultMsg: + fStatusView->UpdateCPUFreqState(); + _UpdateViews(); + break; + default: + BView::MessageReceived(message); + } + + if (configChanged) + Window()->PostMessage(kConfigChangedMsg); +} + + +void +CPUFrequencyView::AttachedToWindow() +{ + fFrequencyMenu = new FrequencyMenu(fPolicyMenu, this, + fStorage, &fDriverInterface); + AddFilter(fFrequencyMenu); + + fColorStepView->SetTarget(this); + fIntegrationTime->SetTarget(this); + fInstallButton->SetTarget(this); + + _UpdateViews(); +} + + +void +CPUFrequencyView::DetachedFromWindow() +{ + // emty menu for the case the view is attached again + while (true) { + BMenuItem* item = fPolicyMenu->RemoveItem(int32(0)); + if (!item) + break; + delete item; + } + if (RemoveFilter(fFrequencyMenu)) + delete fFrequencyMenu; + + _ReadIntegrationTime(); +} + + +status_t +our_image(image_info& image) +{ + int32 cookie = 0; + while (get_next_image_info(B_CURRENT_TEAM, &cookie, &image) == B_OK) { + if ((char *)our_image >= (char *)image.text + && (char *)our_image <= (char *)image.text + image.text_size) + return B_OK; + } + + return B_ERROR; +}; + + +void +CPUFrequencyView::_InstallReplicantInDeskbar() +{ + image_info info; + entry_ref ref; + if (our_image(info) == B_OK + && get_ref_for_path(info.name, &ref) == B_OK) { + BDeskbar deskbar; + deskbar.AddItem(&ref); + } +} + + +void +CPUFrequencyView::_UpdateViews() +{ + fFrequencyMenu->UpdateMenu(); + freq_preferences* pref = fStorage->GetPreferences(); + fColorStepView->SetSliderPosition(pref->stepping_threshold); + if (pref->mode == DYNAMIC) { + fColorStepView->SetEnabled(true); + fIntegrationTime->SetEnabled(true); + } + else { + fColorStepView->SetEnabled(false); + fIntegrationTime->SetEnabled(false); + } + + BString out; + out << pref->integration_time / kMilliSecond; + fIntegrationTime->SetText(out.String()); +} + + +void +CPUFrequencyView::_ReadIntegrationTime() +{ + freq_preferences* pref = fStorage->GetPreferences(); + bigtime_t integration_time = atoi(fIntegrationTime->Text()) * kMilliSecond; + if (integration_time == 0) { + BString out; + out << pref->integration_time / kMilliSecond; + fIntegrationTime->SetText(out.String()); + } + else { + pref->integration_time = integration_time; + } +} diff --git a/src/preferences/cpufrequency/CPUFrequencyView.h b/src/preferences/cpufrequency/CPUFrequencyView.h new file mode 100644 index 0000000000..2a73932a6b --- /dev/null +++ b/src/preferences/cpufrequency/CPUFrequencyView.h @@ -0,0 +1,83 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#ifndef CPUFREQUENCYVIEW_h +#define CPUFREQUENCYVIEW_h + +#include "DriverInterface.h" +#include "ColorStepView.h" +#include "PreferencesWindow.h" + +#include +#include +#include +#include + + +extern const char* kPrefSignature; +extern const char* kPreferencesFileName; + +enum stepping_mode { + DYNAMIC, + PERFORMANCE, + LOW_ENERGIE, + CUSTOM +}; + + +struct freq_preferences +{ + // stepping mode + stepping_mode mode; + int16 custom_stepping; + + // dynamic stepping + float stepping_threshold; + bigtime_t integration_time; +}; + + +const freq_preferences kDefaultPreferences = +{ + DYNAMIC, + -1, + 0.25, + 500000 //half second +}; + + +class FrequencyMenu; +class StatusView; + +class CPUFrequencyView : public BView +{ + public: + CPUFrequencyView(BRect frame, + PreferencesStorage* storage); + virtual void MessageReceived(BMessage* message); + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + private: + void _InstallReplicantInDeskbar(); + void _UpdateViews(); + void _ReadIntegrationTime(); + + BMenu* fPolicyMenu; + FrequencyMenu* fFrequencyMenu; + ColorStepView* fColorStepView; + BTextControl* fIntegrationTime; + StatusView* fStatusView; + BButton* fInstallButton; + + PreferencesStorage* fStorage; + CPUFreqDriverInterface fDriverInterface; +}; + +#endif diff --git a/src/preferences/cpufrequency/ColorStepView.cpp b/src/preferences/cpufrequency/ColorStepView.cpp new file mode 100644 index 0000000000..ec4d4fba21 --- /dev/null +++ b/src/preferences/cpufrequency/ColorStepView.cpp @@ -0,0 +1,329 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#include "ColorStepView.h" + +#include + + +const int32 kColorBarHeight = 15; + +const uint32 kMSGSliderChanged = '&slc'; + + +ColorStepView::ColorStepView(BRect frame) + : BControl(frame, "ColorStepView", "", new BMessage(kSteppingChanged), + B_FOLLOW_ALL, B_WILL_DRAW), + fOffScreenView(NULL), + fOffScreenBitmap(NULL) +{ + fPerformanceList = new PerformanceList(20, true); + + fSliderPosition = 0; + fNSteps = 0; + fLowFreqColor.red = 0; + fLowFreqColor.blue = 255; + fLowFreqColor.green = 0; + + fHighFreqColor.red = 255; + fHighFreqColor.blue = 0; + fHighFreqColor.green = 0; + + fMinFrequencyLabel = "? MHz"; + fMaxFrequencyLabel = "? MHz"; + _InitView(); +} + + +ColorStepView::~ColorStepView() +{ + delete fPerformanceList; +} + + +void +ColorStepView::AttachedToWindow() +{ + fSlider->SetTarget(this); + + if (!fOffScreenView) { + fOffScreenView = new BView(Bounds(), "", B_FOLLOW_ALL, B_WILL_DRAW); + } + if (!fOffScreenBitmap) { + fOffScreenBitmap = new BBitmap(Bounds(), B_CMAP8, true, false); + Window()->Lock(); + if (fOffScreenBitmap && fOffScreenView) + fOffScreenBitmap->AddChild(fOffScreenView); + Window()->Unlock(); + } +} + + +void +ColorStepView::DetachedFromWindow() +{ + BView::DetachedFromWindow(); + + if (fOffScreenBitmap) { + delete fOffScreenBitmap; + fOffScreenBitmap = NULL; + fOffScreenView = NULL; + } +} + + +void +ColorStepView::FrameResized(float w,float h) +{ + BView::FrameResized(w, h); + + BRect bounds(Bounds()); + + if (bounds.right <= 0.0f || bounds.bottom <= 0.0f) + return; + + if (fOffScreenBitmap) { + fOffScreenBitmap->RemoveChild(fOffScreenView); + delete fOffScreenBitmap; + + fOffScreenView->ResizeTo(bounds.Width(), bounds.Height()); + + fOffScreenBitmap = new BBitmap(Bounds(), B_RGBA32, true, false); + fOffScreenBitmap->AddChild(fOffScreenView); + } + + Invalidate(); +} + + +void +ColorStepView::GetPreferredSize(float *width, float *height) +{ + *width = Frame().Width(); + font_height fontHeight; + GetFontHeight(&fontHeight); + + *height = fSlider->Frame().Height(); + *height += kColorBarHeight; + *height += fontHeight.descent + fontHeight.ascent + 5; +} + + +void +ColorStepView::Draw(BRect updateRect) +{ + BView *view = NULL; + if(fOffScreenView){ + view = fOffScreenView; + } + else{ + view = this; + } + + if (!fOffScreenBitmap || !fOffScreenBitmap->Lock()) + return; + view->SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + view->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + view->FillRect(updateRect); + + BRect colorBarRect = fSlider->BarFrame(); + colorBarRect.top = 0; + colorBarRect.bottom = kColorBarHeight; + colorBarRect.OffsetTo(colorBarRect.left, fSlider->Frame().bottom); + + float pos = 0.0; + for (int i = fPerformanceList->CountItems() - 1; i >= 0 ; i--) { + performance_step* perfState = fPerformanceList->ItemAt(i); + + float nextPos = perfState->cpu_usage; + float width = colorBarRect.Width(); + + BRect subRect(colorBarRect); + subRect.left += pos * width; + subRect.right = colorBarRect.left + nextPos * width; + + view->SetHighColor(perfState->color); + view->FillRect(subRect); + + pos = nextPos; + } + // draw label + if (IsEnabled()) { + view->SetHighColor(0, 0, 0); + } else { + view->SetHighColor(tint_color(LowColor(), B_DISABLED_LABEL_TINT)); + } + + font_height fontHeight; + GetFontHeight(&fontHeight); + float totalFontHeight = fontHeight.descent + fontHeight.ascent; + + view->DrawString(fMinFrequencyLabel.String(), + BPoint(0.0, + colorBarRect.bottom + totalFontHeight + 5)); + + view->DrawString(fMaxFrequencyLabel.String(), + BPoint(Bounds().right + - StringWidth(fMaxFrequencyLabel.String()), + colorBarRect.bottom + totalFontHeight + 5)); + + // blit bitmap + fOffScreenView->Sync(); + fOffScreenBitmap->Unlock(); + DrawBitmap(fOffScreenBitmap, B_ORIGIN); + + BView::Draw(updateRect); +} + + +void +ColorStepView::MessageReceived(BMessage *message) +{ + switch (message->what) { + case kMSGSliderChanged: + fSliderPosition = fSlider->Position(); + _CalculatePerformanceSteps(); + Invalidate(); + break; + case kSteppingChanged: + Invoke(); + break; + default: + BView::MessageReceived(message); + break; + } +} + + +void +ColorStepView::SetEnabled(bool enabled) +{ + fSlider->SetEnabled(enabled); + BControl::SetEnabled(enabled); +} + + +void +ColorStepView::SetFrequencys(StateList *list) +{ + fStateList = list; + fNSteps = fStateList->CountItems(); + if (fNSteps >= 2) { + float minFreq = fStateList->ItemAt(fNSteps - 1)->frequency; + float maxFreq = fStateList->ItemAt(0)->frequency; + fMinFrequencyLabel = CreateFrequencyString(minFreq); + fMaxFrequencyLabel = CreateFrequencyString(maxFreq); + } + + // fit size of fPerformanceList + int32 perfNumber = fPerformanceList->CountItems(); + if (perfNumber < fNSteps) { + for (int i = 0; i < fNSteps - perfNumber; i++) + fPerformanceList->AddItem(new performance_step); + } + else { + for (int i = 0; i < perfNumber - fNSteps; i++) + fPerformanceList->RemoveItemAt(0); + } + // and fill the list + _CalculatePerformanceSteps(); + +} + + +PerformanceList* +ColorStepView::GetPerformanceSteps() +{ + return fPerformanceList; +} + + +BString +ColorStepView::CreateFrequencyString(uint16 frequency) +{ + BString string = ""; + if (frequency >= 1000) { + char buffer [10]; + sprintf (buffer, "%.1f", float(frequency) / 1000); + string << buffer; + string += " GHz"; + } + else { + string << frequency; + string += " MHz"; + } + return string; +} + + + +float +ColorStepView::UsageOfStep(int32 step, int32 nSteps, float base) +{ + float singleWidth = (1 - base) / (nSteps - 1); + return base + singleWidth * step; +} + + +void +ColorStepView::_InitView() +{ + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + BRect sliderFrame(Bounds()); + + fSlider = new BSlider(sliderFrame, "StepSlider", "Step up by CPU usage:", + new BMessage(kSteppingChanged), 0, 100); + fSlider->SetModificationMessage(new BMessage(kMSGSliderChanged)); + + fSliderPosition = 0.25 - fNSteps * 0.05; + fSlider->SetPosition(fSliderPosition); + fSlider->SetLimitLabels("0%", "100%"); + fSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); + fSlider->SetHashMarkCount(5); + AddChild(fSlider); +} + + +void +ColorStepView::_CalculatePerformanceSteps() +{ + for (int i = 0; i < fNSteps; i++) { + // begin with the lowest frequency + performance_step* perfState = fPerformanceList->ItemAt(fNSteps -1 - i); + perfState->cpu_usage = _PositonStep(i); + _ColorStep(i, perfState->color); + } +} + + +float +ColorStepView::_PositonStep(int32 step) +{ + if (step >= fNSteps) + return 1.0; + + return UsageOfStep(step, fNSteps, fSliderPosition); +} + + +void +ColorStepView::_ColorStep(int32 step, rgb_color &color) +{ + color.red = fLowFreqColor.red + + (fHighFreqColor.red - fLowFreqColor.red) + / (fNSteps - 1) * step; + color.green = fLowFreqColor.green + + (fHighFreqColor.green - fLowFreqColor.green) + / (fNSteps - 1) * step; + color.blue = fLowFreqColor.blue + + (fHighFreqColor.blue - fLowFreqColor.blue) + / (fNSteps - 1) * step; +} + diff --git a/src/preferences/cpufrequency/ColorStepView.h b/src/preferences/cpufrequency/ColorStepView.h new file mode 100644 index 0000000000..0c44ac5b9b --- /dev/null +++ b/src/preferences/cpufrequency/ColorStepView.h @@ -0,0 +1,82 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#ifndef COLORSTEPVIEW_H +#define COLORSTEPVIEW_H + +#include +#include +#include +#include +#include + +#include "DriverInterface.h" + +const uint32 kSteppingChanged = '&spc'; + +struct performance_step { + float cpu_usage; // upper limit + rgb_color color; +}; + + +typedef BObjectList PerformanceList; + + +class ColorStepView : public BControl +{ + public: + ColorStepView(BRect frame); + ~ColorStepView(); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void FrameResized(float w,float h); + + virtual void GetPreferredSize(float *width, float *height); + virtual void Draw(BRect updateRect); + virtual void MessageReceived(BMessage *message); + virtual void SetEnabled(bool enabled); + + void SetFrequencys(StateList *list); + PerformanceList* GetPerformanceSteps(); + static BString CreateFrequencyString(uint16 frequency); + + void SetSliderPosition(float pos) { + fSlider->SetPosition(pos); + fSliderPosition = pos; + _CalculatePerformanceSteps(); + } + float GetSliderPosition() { return fSliderPosition; } + + static float UsageOfStep(int32 step, int32 nSteps, float base); + + private: + void _InitView(); + void _CalculatePerformanceSteps(); + float _PositonStep(int32 step); + void _ColorStep(int32 step, rgb_color &color); + + BSlider* fSlider; + + float fSliderPosition; + int32 fNSteps; + rgb_color fLowFreqColor; + rgb_color fHighFreqColor; + + BView* fOffScreenView; + BBitmap* fOffScreenBitmap; + + BString fMinFrequencyLabel; + BString fMaxFrequencyLabel; + + PerformanceList* fPerformanceList; + StateList* fStateList; +}; + + +#endif diff --git a/src/preferences/cpufrequency/DriverInterface.cpp b/src/preferences/cpufrequency/DriverInterface.cpp new file mode 100644 index 0000000000..dbc3e909c6 --- /dev/null +++ b/src/preferences/cpufrequency/DriverInterface.cpp @@ -0,0 +1,217 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#include "DriverInterface.h" + +#include +#include +#include +#include + + +#define DRIVER_DIR "/dev/power" + +CPUFreqDriverInterface::CPUFreqDriverInterface() + : fInitOK(false), + fDriverHandler(-1), + fIsWatching(false), + fWatchingMessenger(NULL) +{ + fFrequencyStates = new StateList(20, true); + + if (_FindSpeedStepDriver(DRIVER_DIR) == B_OK) + fInitOK = true; + + status_t ret; + freq_info states[MAX_CPU_FREQUENCY_STATES]; + ret = ioctl(fDriverHandler, GET_CPU_FREQ_STATES, &states, + sizeof(freq_info) * MAX_CPU_FREQUENCY_STATES); + if (ret != B_OK) + return; + + for (int i = 0; i < MAX_CPU_FREQUENCY_STATES && states[i].frequency != 0; + i++) { + fFrequencyStates->AddItem(new freq_info(states[i])); + } +} + + +CPUFreqDriverInterface::~CPUFreqDriverInterface() +{ + delete fFrequencyStates; + + if (InitCheck() == B_OK) + close(fDriverHandler); +} + + +status_t +CPUFreqDriverInterface::InitCheck() +{ + if (fInitOK) + return B_OK; + return B_ERROR; +} + + +StateList* +CPUFreqDriverInterface::GetCpuFrequencyStates() +{ + return fFrequencyStates; +} + + +freq_info* +CPUFreqDriverInterface::GetCurrentFrequencyState() +{ + uint16 stateId = 0; + status_t ret; + ret = ioctl(fDriverHandler, GET_CURENT_CPU_FREQ_STATE, &stateId, + sizeof(uint16)); + if (ret != B_OK) + return NULL; + int32 i = 0; + while (true) { + freq_info* state = fFrequencyStates->ItemAt(i); + if (!state) + break; + i++; + + if (state->id == stateId) + return state; + } + return NULL; +} + + +int32 +CPUFreqDriverInterface::GetNumberOfFrequencyStates() +{ + return fFrequencyStates->CountItems(); +} + + +status_t +CPUFreqDriverInterface::SetFrequencyState(const freq_info* state) +{ + status_t ret; + ret = ioctl(fDriverHandler, SET_CPU_FREQ_STATE, &(state->id), + sizeof(uint16)); + return ret; +} + + +status_t +CPUFreqDriverInterface::StartWatching(BHandler* target) +{ + if (fIsWatching) + return B_ERROR; + + if (fWatchingMessenger) + delete fWatchingMessenger; + fWatchingMessenger = new BMessenger(target); + + status_t status = B_ERROR; + fThreadId = spawn_thread(&_ThreadWatchFreqFunction, "FreqThread", + B_LOW_PRIORITY, this); + if (fThreadId >= 0) + status = resume_thread(fThreadId); + else + return fThreadId; + + if (status == B_OK) { + fIsWatching = true; + return B_OK; + } + return status; +} + + +status_t +CPUFreqDriverInterface::StopWatching() +{ + + if (fIsWatching && + ioctl(fDriverHandler, STOP_WATCHING_CPU_FREQ) == B_OK) + { + delete fWatchingMessenger; + fWatchingMessenger = NULL; + fIsWatching = false; + + status_t status; + return wait_for_thread(fThreadId, &status); + } + + return B_ERROR; +} + + +int32 +CPUFreqDriverInterface::_ThreadWatchFreqFunction(void* data) +{ + CPUFreqDriverInterface* that = (CPUFreqDriverInterface*)data; + that->_WatchFrequency(); + return 0; +} + + +void +CPUFreqDriverInterface::_WatchFrequency() +{ + uint16 newId = 0; + while (ioctl(fDriverHandler, WATCH_CPU_FREQ, &newId, + sizeof(uint16)) == B_OK) + { + int i = 0; + while (true) { + freq_info* state = fFrequencyStates->ItemAt(i); + if (!state) + break; + i++; + + if (state->id == newId) { + BMessage msg(kMSGFrequencyChanged); + msg.AddPointer("freq_info", state); + fWatchingMessenger->SendMessage(&msg); + break; + } + } + } +} + + +status_t +CPUFreqDriverInterface::_FindSpeedStepDriver(const char* path) +{ + BDirectory dir(path); + BEntry entry; + + while (dir.GetNextEntry(&entry) == B_OK) { + BPath path; + entry.GetPath(&path); + + if (entry.IsDirectory()) { + if (_FindSpeedStepDriver(path.Path()) == B_OK) + return B_OK; + } + else { + printf("path %s\n", path.Path()); + fDriverHandler = open(path.Path(), O_RDWR); + if (fDriverHandler >= 0) { + uint32 magicId = 0; + status_t ret; + ret = ioctl(fDriverHandler, IDENTIFY_DEVICE, &magicId, + sizeof(uint32)); + if (ret == B_OK && magicId == kMagicFreqID) + return B_OK; + } + } + + } + return B_ERROR; +} diff --git a/src/preferences/cpufrequency/DriverInterface.h b/src/preferences/cpufrequency/DriverInterface.h new file mode 100644 index 0000000000..7a31f04de9 --- /dev/null +++ b/src/preferences/cpufrequency/DriverInterface.h @@ -0,0 +1,53 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#ifndef DRIVERINTERFACE_H +#define DRIVERINTERFACE_H + +#include +#include + +#include "device/power_managment.h" + +const uint32 kMSGFrequencyChanged = '&frc'; + +typedef BObjectList StateList; + + +class CPUFreqDriverInterface +{ + public: + CPUFreqDriverInterface(); + ~CPUFreqDriverInterface(); + + status_t InitCheck(); + StateList* GetCpuFrequencyStates(); + freq_info* GetCurrentFrequencyState(); + int32 GetNumberOfFrequencyStates(); + status_t SetFrequencyState(const freq_info* state); + + status_t StartWatching(BHandler* target); + status_t StopWatching(); + private: + static int32 _ThreadWatchFreqFunction(void* data); + void _WatchFrequency(); + + thread_id fThreadId; + status_t _FindSpeedStepDriver(const char* path); + + bool fInitOK; + int32 fDriverHandler; + + StateList* fFrequencyStates; + + bool fIsWatching; + BMessenger* fWatchingMessenger; +}; + + +#endif diff --git a/src/preferences/cpufrequency/Jamfile b/src/preferences/cpufrequency/Jamfile new file mode 100644 index 0000000000..26e6101a41 --- /dev/null +++ b/src/preferences/cpufrequency/Jamfile @@ -0,0 +1,13 @@ +SubDir HAIKU_TOP src preferences cpufrequency ; + +UsePrivateHeaders shared ; + +Preference CPUFrequency : + ColorStepView.cpp + CPUFrequencyView.cpp + DriverInterface.cpp + main.cpp + StatusView.cpp + : be + : cpufrequency.rdef + ; diff --git a/src/preferences/cpufrequency/PreferencesWindow.h b/src/preferences/cpufrequency/PreferencesWindow.h new file mode 100644 index 0000000000..90ee52872b --- /dev/null +++ b/src/preferences/cpufrequency/PreferencesWindow.h @@ -0,0 +1,439 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#ifndef PREFERENCESWINDOW_h +#define PREFERENCESWINDOW_h + +#define DEBUG 1 +#include + +#if DEBUG +# define LOG(text...) PRINT((text)) +#else +# define LOG(text...) +#endif + +#include +#include +#include +#include + +// headers PreferencesStorage +#include +#include +#include +#include + +// headers PrefFileWatcher +#include + +// headers PreferencesWindow +#include +#include +#include + + +// messages PrefFileWatcher +const uint32 kUpdatedPreferences = '&UdP'; + +template +class PreferencesStorage +{ + public: + PreferencesStorage(const char* file, + const Preferences& defaultPreferences); + ~PreferencesStorage(); + + void Revert(); + void Defaults(); + + BPoint WindowPosition(){return fWindowPosition;} + void SetWindowPosition(BPoint position){ + fWindowPosition = position;} + + Preferences* GetPreferences(){return &fPreferences;} + + status_t LoadPreferences(); + status_t SavePreferences(); + + BString& PreferencesFile() { return fPreferencesFile; } + status_t GetPreferencesPath(BPath &path); + + private: + BString fPreferencesFile; + + Preferences fPreferences; + Preferences fStartPreferences; + const Preferences& fDefaultPreferences; + BPoint fWindowPosition; +}; + + +template +class PrefFileWatcher : public BMessageFilter +{ + public: + PrefFileWatcher(PreferencesStorage* storage, + BHandler* target); + ~PrefFileWatcher(); + virtual filter_result Filter(BMessage *message, BHandler **target); + + private: + PreferencesStorage* fPreferencesStorage; + node_ref fPreferencesNode; + node_ref fPreferencesDirectoryNode; + + BHandler* fTarget; +}; + + +template +class PreferencesWindow : public BWindow, public PreferencesStorage +{ + public: + PreferencesWindow(const char* title, + const char* file, + const Preferences& defaultPreferences); + ~PreferencesWindow(); + virtual void MessageReceived(BMessage *msg); + virtual bool QuitRequested(); + + virtual bool SetPreferencesView(BView* prefView); + + private: + void _MoveToPosition(); + BView* fPreferencesView; + BButton* fRevertButton; + BButton* fDefaultButton; + BGroupLayout* fRootLayout; +}; + + +const uint32 kDefaultMsg = 'dems'; +const uint32 kRevertMsg = 'rems'; +const uint32 kConfigChangedMsg = '&cgh'; + +template +PreferencesStorage::PreferencesStorage(const char* file, + const Preferences& defaultPreferences) + : fDefaultPreferences(defaultPreferences) +{ + // default center position + fWindowPosition.x = -1; + fWindowPosition.y = -1; + + fPreferencesFile = file; + if (LoadPreferences() != B_OK) + Defaults(); + fStartPreferences = fPreferences; +} + + +template +PreferencesStorage::~PreferencesStorage() +{ + SavePreferences(); +} + + +template +void +PreferencesStorage::Revert() +{ + fPreferences = fStartPreferences; +} + + +template +void +PreferencesStorage::Defaults() +{ + fPreferences = fDefaultPreferences; +} + + +template +status_t +PreferencesStorage::GetPreferencesPath(BPath &path) +{ + status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); + if (status < B_OK) + return status; + + return path.Append(fPreferencesFile.String()); +} + + +template +status_t +PreferencesStorage::LoadPreferences() +{ + BPath path; + status_t status = GetPreferencesPath(path); + if (status != B_OK) + return status; + + BFile settingsFile(path.Path(), B_READ_ONLY); + status = settingsFile.InitCheck(); + if (status != B_OK) + return status; + + if (settingsFile.Read(&fWindowPosition, sizeof(BPoint)) + != sizeof(BPoint)) { + LOG("failed to load settings\n"); + return B_ERROR; + } + + if (settingsFile.Read(&fPreferences, sizeof(Preferences)) + != sizeof(Preferences)) { + LOG("failed to load settings\n"); + return B_ERROR; + } + + return B_OK; +} + + +template +status_t +PreferencesStorage::SavePreferences() +{ + BPath path; + status_t status = GetPreferencesPath(path); + if (status != B_OK) + return status; + + BFile settingsFile(path.Path(), B_READ_WRITE | B_CREATE_FILE); + status = settingsFile.InitCheck(); + if (status != B_OK) { + LOG("InitCheck() settings file failed \n"); + return status; + } + + if (settingsFile.Write(&fWindowPosition, sizeof(BPoint)) + != sizeof(BPoint)) { + LOG("can't save window position\n"); + return B_ERROR; + } + + if (settingsFile.Write(&fPreferences, sizeof(Preferences)) + != sizeof(Preferences)) { + LOG("can't save settings\n"); + return B_ERROR; + } + + return B_OK; +} + + +template +PrefFileWatcher::PrefFileWatcher(PreferencesStorage* storage, + BHandler* target) + : BMessageFilter(B_PROGRAMMED_DELIVERY, B_ANY_SOURCE), + fPreferencesStorage(storage), + fTarget(target) +{ + BPath path; + find_directory(B_USER_SETTINGS_DIRECTORY, &path); + BEntry entry(path.Path()); + entry.GetNodeRef(&fPreferencesDirectoryNode); + watch_node(&fPreferencesDirectoryNode, B_WATCH_DIRECTORY, + fTarget); + path.Append(fPreferencesStorage->PreferencesFile().String()); + entry.SetTo(path.Path()); + entry.GetNodeRef(&fPreferencesNode); + watch_node(&fPreferencesNode, B_WATCH_STAT, + fTarget); +} + + +template +PrefFileWatcher::~PrefFileWatcher() +{ + stop_watching(fTarget); +} + + +template +filter_result +PrefFileWatcher::Filter(BMessage *msg, BHandler **target) +{ + const char *name; + ino_t dir = -1; + filter_result result = B_DISPATCH_MESSAGE; + int32 opcode; + BPath path; + node_ref nref; + + if (msg->what != B_NODE_MONITOR + || msg->FindInt32("opcode", &opcode) != B_OK) + return result; + + switch(opcode) + { + case B_ENTRY_MOVED: + msg->FindInt64("to directory", dir); + if (dir != fPreferencesDirectoryNode.node) + break; + + case B_ENTRY_CREATED: + msg->FindString("name", &name); + fPreferencesStorage->GetPreferencesPath(path); + if (path.Path() == name) { + msg->FindInt32("device", &fPreferencesNode.device); + msg->FindInt64("node", &fPreferencesNode.node); + watch_node(&fPreferencesNode, B_WATCH_STAT, fTarget); + } + fPreferencesStorage->LoadPreferences(); + msg->what = kUpdatedPreferences; + break; + + case B_ENTRY_REMOVED: + msg->FindInt32("device", &nref.device); + msg->FindInt64("node", &nref.node); + if (fPreferencesNode == nref) { + // stop all watching + stop_watching(fTarget); + // and start watching the directory again + watch_node(&fPreferencesDirectoryNode, B_WATCH_DIRECTORY, + fTarget); + msg->what = kUpdatedPreferences; + } + break; + + case B_STAT_CHANGED: + msg->FindInt32("device", &nref.device); + msg->FindInt64("node", &nref.node); + if (fPreferencesNode == nref) { + fPreferencesStorage->LoadPreferences(); + msg->what = kUpdatedPreferences; + } + break; + } + return result; +} + + +template +PreferencesWindow::PreferencesWindow(const char* title, + const char* file, + const Preferences& defaultPreferences) + : BWindow(BRect(50, 50, 400, 350), title, B_TITLED_WINDOW, + B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_AVOID_FRONT + | B_ASYNCHRONOUS_CONTROLS), + PreferencesStorage(file, defaultPreferences), + fPreferencesView(NULL) +{ + BGroupView* buttonView = new BGroupView(B_HORIZONTAL); + fDefaultButton = new BButton("Defaults", + new BMessage(kDefaultMsg)); + + buttonView->AddChild(fDefaultButton); + buttonView->GetLayout()->AddItem(BSpaceLayoutItem::CreateHorizontalStrut(7)); + fRevertButton = new BButton("Revert", new BMessage(kRevertMsg)); + + fRevertButton->SetEnabled(false); + buttonView->AddChild(fRevertButton); + buttonView->GetLayout()->AddItem(BSpaceLayoutItem::CreateGlue()); + + SetLayout(new BGroupLayout(B_VERTICAL)); + fRootLayout = new BGroupLayout(B_VERTICAL); + fRootLayout->SetInsets(10, 10, 10, 10); + fRootLayout->SetSpacing(10); + BView* rootView = new BView("root view", 0, fRootLayout); + AddChild(rootView); + rootView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + fRootLayout->AddView(buttonView); + + BSize size = fRootLayout->PreferredSize(); + ResizeTo(size.width, size.height); + _MoveToPosition(); +} + + +template +PreferencesWindow::~PreferencesWindow() +{ + SetWindowPosition(Frame().LeftTop()); +} + + +template +void +PreferencesWindow::MessageReceived(BMessage *msg) +{ + switch(msg->what) + { + case kConfigChangedMsg: + fRevertButton->SetEnabled(true); + break; + + case kDefaultMsg: + Defaults(); + fRevertButton->SetEnabled(true); + if (fPreferencesView) + PostMessage(kDefaultMsg, fPreferencesView); + break; + + case kRevertMsg: + Revert(); + fRevertButton->SetEnabled(false); + if (fPreferencesView) + PostMessage(kRevertMsg, fPreferencesView); + break; + + default: + BWindow::MessageReceived(msg); + } +} + + +template +bool +PreferencesWindow::QuitRequested() +{ + be_app->PostMessage(B_QUIT_REQUESTED); + return true; +} + + +template +bool +PreferencesWindow::SetPreferencesView(BView* prefView) +{ + if (fPreferencesView) + return false; + + fPreferencesView = prefView; + fRootLayout->AddView(0, fPreferencesView); + + BSize size = fRootLayout->PreferredSize(); + ResizeTo(size.width, size.height); + _MoveToPosition(); + + return true; +} + + +template +void +PreferencesWindow::_MoveToPosition() +{ + BPoint position = WindowPosition(); + // center window on screen if it had a bad position + if(position.x < 0 && position.y < 0){ + BRect rect = BScreen().Frame(); + BRect windowFrame = Frame(); + position.x = (rect.Width() - windowFrame.Width()) / 2; + position.y = (rect.Height() - windowFrame.Height()) / 2; + } + MoveTo(position); +} + +#endif diff --git a/src/preferences/cpufrequency/StatusView.cpp b/src/preferences/cpufrequency/StatusView.cpp new file mode 100644 index 0000000000..f338daa800 --- /dev/null +++ b/src/preferences/cpufrequency/StatusView.cpp @@ -0,0 +1,666 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#include "StatusView.h" +#include "CPUFrequencyView.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern "C" _EXPORT BView *instantiate_deskbar_item(void); + +// messages FrequencySwitcher +const uint32 kMsgDynamicPolicyPuls = '&dpp'; + +// messages menu +const uint32 kMsgPolicyDynamic = 'pody'; +const uint32 kMsgPolicyPerformance = 'popr'; +const uint32 kMsgPolicyLowEnergy = 'pole'; +const uint32 kMsgPolicySetState = 'poss'; + +// messages StatusView +const uint32 kMsgOpenSSPreferences = 'ossp'; +const char* kDeskbarItemName = "CPUFreqStatusView"; + + +FrequencySwitcher::FrequencySwitcher(CPUFreqDriverInterface* interface, + BHandler* target) + : BMessageFilter(B_PROGRAMMED_DELIVERY, B_ANY_SOURCE), + fDriverInterface(interface), + fTarget(target), + fMessageRunner(NULL), + fCurrentFrequency(NULL), + fDynamicPolicyStarted(false) +{ + +} + + +FrequencySwitcher::~FrequencySwitcher() +{ + freq_preferences dummyPref; + _StartDynamicPolicy(false, dummyPref); +} + + +filter_result +FrequencySwitcher::Filter(BMessage *message, BHandler **target) +{ + filter_result result = B_DISPATCH_MESSAGE; + if (message->what == kMsgDynamicPolicyPuls) { + _CalculateDynamicState(); + result = B_SKIP_MESSAGE; + } + return result; +} + + +void +FrequencySwitcher::SetMode(const freq_preferences& pref) +{ + int16 stateCount = fDriverInterface->GetNumberOfFrequencyStates(); + StateList* list = fDriverInterface->GetCpuFrequencyStates(); + freq_info* currentState = fDriverInterface->GetCurrentFrequencyState(); + freq_info* state = NULL; + bool isDynamic = false; + + switch (pref.mode) { + case DYNAMIC: + isDynamic = true; + fSteppingThreshold = pref.stepping_threshold; + if (fMessageRunner && fIntegrationTime != pref.integration_time) + { + fIntegrationTime = pref.integration_time; + fMessageRunner->SetInterval(fIntegrationTime); + } + if (!fDynamicPolicyStarted) + _StartDynamicPolicy(true, pref); + break; + + case PERFORMANCE: + state = list->ItemAt(int32(0)); + if (state != currentState) + fDriverInterface->SetFrequencyState(state); + break; + + case LOW_ENERGIE: + state = list->ItemAt(stateCount - 1); + if (state != currentState) + fDriverInterface->SetFrequencyState(state); + break; + + case CUSTOM: + if (pref.custom_stepping < stateCount) { + state = list->ItemAt(pref.custom_stepping); + fDriverInterface->SetFrequencyState(state); + } + break; + } + + if (!isDynamic && fDynamicPolicyStarted) { + fDynamicPolicyStarted = false; + _StartDynamicPolicy(false, pref); + } +} + + +void +FrequencySwitcher::_CalculateDynamicState() +{ + system_info sysInfo; + get_system_info(&sysInfo); + bigtime_t now = system_time(); + bigtime_t activeTime = sysInfo.cpu_infos[0].active_time; + + // if the dynamic mode is not started firt init the prev values + if (!fDynamicPolicyStarted) { + fPrevActiveTime = activeTime; + fPrevTime = now; + fDynamicPolicyStarted = true; + } + else { + float usage = (float)(activeTime - fPrevActiveTime ) + / (now - fPrevTime); + if (usage >= 1.0) + usage = 0.9999999; + + int32 numberOfStates = fDriverInterface->GetNumberOfFrequencyStates(); + for (int i = 0; i < numberOfStates; i++) { + float usageOfStep = ColorStepView::UsageOfStep(i, numberOfStates, + fSteppingThreshold); + LOG("usage %f, step %f\n", usage, usageOfStep); + + if (usage < usageOfStep) + { + StateList* list = fDriverInterface->GetCpuFrequencyStates(); + freq_info* newState = list->ItemAt(numberOfStates - 1 - i); + if (newState != fCurrentFrequency) { + LOG("change freq\n"); + fDriverInterface->SetFrequencyState(newState); + fCurrentFrequency = newState; + } + break; + } + } + fPrevActiveTime = activeTime; + fPrevTime = now; + } +} + + +void +FrequencySwitcher::_StartDynamicPolicy(bool start, + const freq_preferences& pref) +{ + if (start) { + if (!fMessageRunner) { + fIntegrationTime = pref.integration_time; + fMessageRunner = new BMessageRunner(fTarget, + new BMessage(kMsgDynamicPolicyPuls) + , pref.integration_time, -1); + fCurrentFrequency = fDriverInterface->GetCurrentFrequencyState(); + } + } + else { + if (fMessageRunner) { + delete fMessageRunner; + fMessageRunner = NULL; + } + } +} + + +FrequencyMenu::FrequencyMenu(BMenu* menu, BHandler* target, + PreferencesStorage * storage, + CPUFreqDriverInterface* interface) + : BMessageFilter(B_PROGRAMMED_DELIVERY, B_LOCAL_SOURCE), + fTarget(target), + fStorage(storage), + fInterface(interface) +{ + fDynamicPerformance = new BMenuItem("Dynamic Performance", + new BMessage(kMsgPolicyDynamic)); + fHighPerformance = new BMenuItem("High Performance", + new BMessage(kMsgPolicyPerformance)); + fLowEnergie = new BMenuItem("Low Energie", + new BMessage(kMsgPolicyLowEnergy)); + + menu->AddItem(fDynamicPerformance); + menu->AddItem(fHighPerformance); + menu->AddItem(fLowEnergie); + + fCustomStateMenu = new BMenu("Set State"); + + StateList* stateList = fInterface->GetCpuFrequencyStates(); + for (int i = 0; i < stateList->CountItems(); i++) { + freq_info* info = stateList->ItemAt(i); + BString label; + label << info->frequency; + label += " MHz"; + fCustomStateMenu->AddItem(new BMenuItem(label.String(), + new BMessage(kMsgPolicySetState))); + } + + menu->AddItem(fCustomStateMenu); + + // set the target of the items + fDynamicPerformance->SetTarget(fTarget); + fHighPerformance->SetTarget(fTarget); + fLowEnergie->SetTarget(fTarget); + + fCustomStateMenu->SetTargetForItems(fTarget); +} + + +inline void +FrequencyMenu::_SetL1MenuLabelFrom(BMenuItem* item) +{ + BMenuItem* superItem, *markedItem; + superItem = item->Menu()->Superitem(); + if (superItem) + superItem->SetLabel(item->Label()); + markedItem = item->Menu()->FindMarked(); + if (markedItem) + markedItem->SetMarked(false); + item->SetMarked(true); +} + + +filter_result +FrequencyMenu::Filter(BMessage *msg, BHandler **target) +{ + filter_result result = B_DISPATCH_MESSAGE; + + BMenuItem* item, *superItem, *markedItem; + msg->FindPointer("source", (void**)&item); + if (!item) { + return result; + } + + bool safeChanges = false; + freq_preferences* pref = fStorage->GetPreferences(); + + switch (msg->what) { + case kMsgPolicyDynamic: + pref->mode = DYNAMIC; + _SetL1MenuLabelFrom(item); + safeChanges = true; + msg->what = kUpdatedPreferences; + break; + + case kMsgPolicyPerformance: + pref->mode = PERFORMANCE; + _SetL1MenuLabelFrom(item); + safeChanges = true; + msg->what = kUpdatedPreferences; + break; + + case kMsgPolicyLowEnergy: + pref->mode = LOW_ENERGIE; + _SetL1MenuLabelFrom(item); + safeChanges = true; + msg->what = kUpdatedPreferences; + break; + + case kMsgPolicySetState: + pref->mode = CUSTOM; + pref->custom_stepping = item->Menu()->IndexOf(item); + + superItem = item->Menu()->Supermenu()->Superitem(); + if (superItem) + superItem->SetLabel(item->Label()); + markedItem = item->Menu()->Supermenu()->FindMarked(); + if (markedItem) + markedItem->SetMarked(false); + markedItem = item->Menu()->FindMarked(); + if (markedItem) + markedItem->SetMarked(false); + item->SetMarked(true); + + safeChanges = true; + msg->what = kUpdatedPreferences; + break; + } + + if (safeChanges) + fStorage->SavePreferences(); + + return result; +} + + +void +FrequencyMenu::UpdateMenu() +{ + BMenuItem* customItem, *markedItem, *superItem; + + freq_preferences* pref = fStorage->GetPreferences(); + switch (pref->mode) { + case DYNAMIC: + _SetL1MenuLabelFrom(fDynamicPerformance); + break; + + case PERFORMANCE: + _SetL1MenuLabelFrom(fHighPerformance); + break; + + case LOW_ENERGIE: + _SetL1MenuLabelFrom(fLowEnergie); + break; + + case CUSTOM: + markedItem = fCustomStateMenu->FindMarked(); + if (markedItem) + markedItem->SetMarked(false); + customItem = fCustomStateMenu->ItemAt(pref->custom_stepping); + if (customItem) + customItem->SetMarked(true); + superItem = fCustomStateMenu->Supermenu()->Superitem(); + if (superItem && customItem) + superItem->SetLabel(customItem->Label()); + break; + } +} + + +StatusView::StatusView(BRect frame, bool inDeskbar, + PreferencesStorage* storage = NULL) + : BView(frame, kDeskbarItemName, B_FOLLOW_LEFT | B_FOLLOW_TOP, + B_WILL_DRAW | B_FRAME_EVENTS), + fInDeskbar(inDeskbar), + fCurrentFrequency(NULL), + fDragger(NULL) +{ + if (!inDeskbar) { + // we were obviously added to a standard window - let's add a dragger + BRect bounds = Bounds(); + bounds.top = bounds.bottom - 7; + bounds.left = bounds.right - 7; + fDragger = new BDragger(bounds, this, + B_FOLLOW_NONE); + AddChild(fDragger); + } + + if (storage) { + fOwningStorage = false; + fStorage = storage; + } + else { + fOwningStorage = true; + fStorage = new PreferencesStorage("CPUFrequency", + kDefaultPreferences); + } + + _Init(); +} + + +StatusView::StatusView(BMessage* archive) + : BView(archive), + fInDeskbar(false), + fCurrentFrequency(NULL), + fDragger(NULL) +{ + app_info info; + if (be_app->GetAppInfo(&info) == B_OK + && !strcasecmp(info.signature, "application/x-vnd.Be-TSKB")) + fInDeskbar = true; + + fOwningStorage = true; + fStorage = new PreferencesStorage(kPreferencesFileName, + kDefaultPreferences); + _Init(); +} + + +StatusView::~StatusView() +{ + if (fOwningStorage) + delete fStorage; +} + + +void +StatusView::_AboutRequested() +{ + BAlert *alert = new BAlert("about", "CPU Frequency\n" + "\twritten by Clemens Zeidler\n" + "\tCopyright 2009, Haiku, Inc.\n", "Ok"); + BTextView *view = alert->TextView(); + BFont font; + + view->SetStylable(true); + + view->GetFont(&font); + font.SetSize(18); + font.SetFace(B_BOLD_FACE); + view->SetFontAndColor(0, 13, &font); + + alert->Go(); +} + + +void +StatusView::_Quit() +{ + if (fInDeskbar) { + BDeskbar deskbar; + deskbar.RemoveItem(kDeskbarItemName); + } else + be_app->PostMessage(B_QUIT_REQUESTED); +} + + +StatusView * +StatusView::Instantiate(BMessage* archive) +{ + if (!validate_instantiation(archive, "StatusView")) + return NULL; + + return new StatusView(archive); +} + + +status_t +StatusView::Archive(BMessage* archive, bool deep) const +{ + status_t status = BView::Archive(archive, deep); + if (status == B_OK) + status = archive->AddString("add_on", kPrefSignature); + if (status == B_OK) + status = archive->AddString("class", "StatusView"); + + return status; +} + + +void +StatusView::AttachedToWindow() +{ + BView::AttachedToWindow(); + if (Parent()) + SetViewColor(Parent()->ViewColor()); + else + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + SetLowColor(ViewColor()); + + // watching if the driver change the frequency + fDriverInterface.StartWatching(this); + + // monitor preferences file + fPrefFileWatcher = new PrefFileWatcher(fStorage, this); + AddFilter(fPrefFileWatcher); + + // FrequencySwitcher + fFrequencySwitcher = new FrequencySwitcher(&fDriverInterface, this); + fFrequencySwitcher->SetMode(*(fStorage->GetPreferences())); + AddFilter(fFrequencySwitcher); + + // perferences menu + fPreferencesMenu = new BPopUpMenu(B_EMPTY_STRING, false, false); + fPreferencesMenuFilter = new FrequencyMenu(fPreferencesMenu, this, + fStorage, + &fDriverInterface); + + fPreferencesMenu->SetFont(be_plain_font); + + fPreferencesMenu->AddSeparatorItem(); + fOpenPrefItem = new BMenuItem("Open Speedstep Preferences" B_UTF8_ELLIPSIS, + new BMessage(kMsgOpenSSPreferences)); + fPreferencesMenu->AddItem(fOpenPrefItem); + fOpenPrefItem->SetTarget(this); + + if (fInDeskbar) { + fQuitItem= new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED)); + fPreferencesMenu->AddItem(fQuitItem); + fQuitItem->SetTarget(this); + } + AddFilter(fPreferencesMenuFilter); + + fPreferencesMenuFilter->UpdateMenu(); +} + + +void +StatusView::DetachedFromWindow() +{ + fDriverInterface.StopWatching(); + + if (RemoveFilter(fPrefFileWatcher)) + delete fPrefFileWatcher; + if (RemoveFilter(fFrequencySwitcher)) + delete fFrequencySwitcher; + if (RemoveFilter(fPreferencesMenuFilter)) + delete fPreferencesMenuFilter; + delete fPreferencesMenu; +} + + +void +StatusView::MessageReceived(BMessage* message) +{ + switch (message->what) { + case kMsgOpenSSPreferences: + _OpenPreferences(); + break; + + case kMSGFrequencyChanged: + message->FindPointer("freq_info", (void**)&fCurrentFrequency); + _SetupNewFreqString(); + Invalidate(); + break; + + case kUpdatedPreferences: + fFrequencySwitcher->SetMode(*(fStorage->GetPreferences())); + fPreferencesMenuFilter->UpdateMenu(); + break; + + case B_ABOUT_REQUESTED: + _AboutRequested(); + break; + + case B_QUIT_REQUESTED: + _Quit(); + break; + + default: + BView::MessageReceived(message); + } +} + + +void +StatusView::FrameResized(float width, float height) +{ + Invalidate(); +} + + +void +StatusView::Draw(BRect updateRect) +{ + + + font_height fontHeight; + GetFontHeight(&fontHeight); + float height = fontHeight.ascent + fontHeight.descent; + + MovePenTo(0, height); + + DrawString(fFreqString.String()); +} + + + + +void +StatusView::MouseDown(BPoint point) +{ + if (fShowPopUpMenu) { + ConvertToScreen(&point); + fPreferencesMenu->Go(point, true, false, true); + } +} + + +void +StatusView::GetPreferredSize(float *width, float *height) +{ + font_height fontHeight; + GetFontHeight(&fontHeight); + *height = fontHeight.ascent + fontHeight.descent; + if (!fInDeskbar) + *height += 7; + + *width = StringWidth(fFreqString.String()); +} + + +void +StatusView::ResizeToPreferred(void) +{ + float width, height; + GetPreferredSize(&width, &height); + ResizeTo(width, height); +} + + +void +StatusView::ShowPopUpMenu(bool show = true) +{ + fShowPopUpMenu = show; +} + + +void +StatusView::UpdateCPUFreqState() +{ + fFrequencySwitcher->SetMode(*(fStorage->GetPreferences())); +} + + +void +StatusView::_Init() +{ + fShowPopUpMenu = true; + fCurrentFrequency = fDriverInterface.GetCurrentFrequencyState(); + + _SetupNewFreqString(); +} + + +void +StatusView::_SetupNewFreqString() +{ + if (fCurrentFrequency) + fFreqString = ColorStepView::CreateFrequencyString( + fCurrentFrequency->frequency); + else + fFreqString = "? MHz"; + + ResizeToPreferred(); + + if (fDragger) { + BRect frame = Frame(); + fDragger->MoveTo(frame.right - 7, frame.bottom - 7); + } +} + +void +StatusView::_OpenPreferences() +{ + status_t ret = be_roster->Launch(kPrefSignature); + if (ret < B_OK) { + BString errorMessage("Launching the CPU Frequency preflet failed.\n\n" + "Error: "); + errorMessage << strerror(ret); + BAlert* alert = new BAlert("launch error", errorMessage.String(), + "Ok"); + // asynchronous alert in order to not block replicant host + // application + alert->Go(NULL); + } + +} + + +extern "C" _EXPORT BView * +instantiate_deskbar_item(void) +{ + return new StatusView(BRect(0, 0, 15, 15), true, NULL); +} diff --git a/src/preferences/cpufrequency/StatusView.h b/src/preferences/cpufrequency/StatusView.h new file mode 100644 index 0000000000..aac1a64992 --- /dev/null +++ b/src/preferences/cpufrequency/StatusView.h @@ -0,0 +1,140 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#ifndef STATUS_VIEW_H +#define STATUS_VIEW_H + +#include +#include +#include +#include +#include + +#include "CPUFrequencyView.h" +#include "DriverInterface.h" +#include "PreferencesWindow.h" + +#define DEBUG 1 +#include + +#if DEBUG +# define LOG(text...) PRINT((text)) +#else +# define LOG(text...) +#endif + +extern const char* kDeskbarItemName; +extern const char* kAddonSignature; + + +class FrequencySwitcher : public BMessageFilter +{ + public: + FrequencySwitcher(CPUFreqDriverInterface* interface, + BHandler* target); + virtual ~FrequencySwitcher(); + + virtual filter_result Filter(BMessage *message, BHandler **target); + + void SetMode(const freq_preferences& pref); + + private: + void _CalculateDynamicState(); + void _StartDynamicPolicy(bool start, + const freq_preferences& pref); + + CPUFreqDriverInterface* fDriverInterface; + BHandler* fTarget; + BMessageRunner* fMessageRunner; + + freq_info* fCurrentFrequency; + + bool fDynamicPolicyStarted; + bigtime_t fPrevActiveTime; + bigtime_t fPrevTime; + float fSteppingThreshold; + bigtime_t fIntegrationTime; +}; + + +class FrequencyMenu : public BMessageFilter +{ + public: + FrequencyMenu(BMenu* menu, BHandler* target, + PreferencesStorage* storage, + CPUFreqDriverInterface* interface); + virtual filter_result Filter(BMessage *message, BHandler **target); + + void UpdateMenu(); + private: + inline void _SetL1MenuLabelFrom(BMenuItem* item); + + BHandler* fTarget; + BMenuItem* fDynamicPerformance; + BMenuItem* fHighPerformance; + BMenuItem* fLowEnergie; + BMenu* fCustomStateMenu; + + PreferencesStorage* fStorage; + CPUFreqDriverInterface* fInterface; +}; + + +class StatusView : public BView { + public: + StatusView(BRect frame, bool inDeskbar = false, + PreferencesStorage* storage = NULL); + StatusView(BMessage* archive); + virtual ~StatusView(); + + static StatusView* Instantiate(BMessage* archive); + virtual status_t Archive(BMessage* archive, bool deep = true) const; + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + virtual void MessageReceived(BMessage* message); + virtual void FrameResized(float width, float height); + virtual void MouseDown(BPoint where); + virtual void Draw(BRect updateRect); + + virtual void GetPreferredSize(float *width, float *height); + virtual void ResizeToPreferred(void); + + virtual void ShowPopUpMenu(bool show = true); + + virtual void UpdateCPUFreqState(); + + private: + void _Init(); + void _SetupNewFreqString(); + void _OpenPreferences(); + void _AboutRequested(); + void _Quit(); + + bool fInDeskbar; + + CPUFreqDriverInterface fDriverInterface; + freq_info* fCurrentFrequency; + FrequencySwitcher* fFrequencySwitcher; + + bool fShowPopUpMenu; + BPopUpMenu* fPreferencesMenu; + BMenuItem* fOpenPrefItem; + BMenuItem* fQuitItem; + + FrequencyMenu* fPreferencesMenuFilter; + bool fOwningStorage; + PreferencesStorage* fStorage; + PrefFileWatcher* fPrefFileWatcher; + + BString fFreqString; + BDragger* fDragger; +}; + +#endif // STATUS_VIEW_H diff --git a/src/preferences/cpufrequency/cpufrequency.rdef b/src/preferences/cpufrequency/cpufrequency.rdef new file mode 100644 index 0000000000..d4ae66d5da --- /dev/null +++ b/src/preferences/cpufrequency/cpufrequency.rdef @@ -0,0 +1,102 @@ + +resource app_signature "application/x-vnd.Haiku-CPUFrequencyPref"; + +resource app_version { + major = 1, + middle = 0, + minor = 0, + + variety = B_APPV_FINAL, + internal = 0, + + short_info = "CPUFrequency", + long_info = "CPUFrequency ©2008 Haiku, Inc." +}; + +resource app_flags B_SINGLE_LAUNCH; + +#ifdef HAIKU_TARGET_PLATFORM_HAIKU + +resource vector_icon { + $"6E6369660E03010000020002023980000000000000004000004BE00008908100" + $"010000FFFF01000000020016023CC7EE389BC0BA16573E39B04977C842ADC700" + $"FFFFD3020006023C529D3753A2B8966F3D9D084B6044496AAF00474747FFA5A0" + $"A002001602BC4E76BC411B3C90DABCA00D47587D4ABA850090FFD40200160238" + $"313C3B5CF0BFCD963C7AAC4C13943FCAF901ECFFC3054B04017E020006033E2F" + $"99387F17BA42DB3FF5B94A0E32482C90001D1E2C3D454658FF01010102000602" + $"3879063B8224BE2CC83B10DB4A1F6F49B894FF9A9A9A00242222020006033C69" + $"A60000000000003E186148800049800058F3F3F300D4CECEFFD9D9D902000603" + $"3C1F1A33E78CB7ACC03FFE4F48BB3EBD7B6C0078D905818CFF05FF7ADD050200" + $"1602349C2E37B5FABA1F6036FC624A3E004B320001D3FF910200160235777837" + $"0A67B7E8CE363A844A1D684B45D800F3FF2E0D0A04486050605C51544E04033E" + $"5349594856475C49604B5C4E604B0A06262A264C485E5252523030240A04262A" + $"4838523030240A044838485E525252300A04262A264C485E48380A04453A4553" + $"2844282E0A04B6F9C0F42845282EB701B8EC0A044550455328452AC0F30A0445" + $"3A45502A43B701B8EC0408AEBAB6BCBCC32FBD4F2E3930BDA8B9ACC0A5BA9EBC" + $"03BB1EBFD937BF0DBD4FC072BCC3C019BDDBC0CB46460204BF23C726BF91C70D" + $"BEB5C73FBE9FC87EBE7AC7D9BEC5C922BFAAC97BBF3CC994C018C962C02DC823" + $"C053C8C8C008C77F0204BFCEC6FBC042C6E0BF5BC715BF48C85ABF1FC7B3BF71" + $"C902C063C95ABFF0C974C0D7C93FC0EAC7FAC113C8A2C0C1C7530E0A07010000" + $"0A0101011001178300040A0001021001178400040A020103000A080109000A0B" + $"010A1001178120040A030104000A04020506000A090107000A0A0108000A0D01" + $"0C0815FF0A0C010B0815FF0A0D010C0A3FEAF70000000000003FEAF7C573B4C2" + $"770615FF0A0C010B0A3FEAF70000000000003FEAF7C573B4C2770615FF" +}; + +#else // HAIKU_TARGET_PLATFORM_HAIKU + +resource large_icon array { + $"FFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFF001B1C0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFF001B1C1B1C1C0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFF001B1C1B1C1C1B1C1C0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFF001B1C1B1C1C1B1C1C1B1C1B0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFF001B1C1B1C1C1B1C1C1B1C1B1C1C1B0000FFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FF001B1C1B1C1C1B1C1C1B1C1B1C1C1B1C1C1B0000FFFFFFFFFFFFFFFFFFFFFF" + $"003F1B1C1B1C1C1B1C1C1B1C1B1C1C1B1C1C1B1C1B0000FFFFFFFFFFFFFFFFFF" + $"00173F3F1B1C1B1C1C1B1C1C1B1C1B1C1C1B1C1C1B1C3F00FFFFFFFFFFFFFFFF" + $"001717183F3F1B1C1B1C1C1B1C1C1B1C1B1C1C1B1C3F0E00FFFFFFFFFFFFFFFF" + $"00170F1718173F3F1B1C1B1C1C1B1C1C1B1C1B1C3F0E0F00FFFFFFFFFFFFFFFF" + $"00170F0F0F1717183F3F1B1C1B1C1C1B1C1C1B3F0E0F0F00FFFFFFFFFFFFFFFF" + $"00170F00000F0F1717183F3F1B1C1B1C1C1B3F0E0F0F0F00FFFFFFFFFFFFFFFF" + $"00170F000000000F0F1717183F3F1B1C1B3F0E0F0F0F0F00FFFFFFFFFFFFFFFF" + $"00170F0000000000000F0F1717183F1B3F0E0F0F0F0F0F00FFFFFFFFFFFFFFFF" + $"00170F00003700000000000F0F17173F0E0F0F0F0F0F0F00FFFFFFFF000000FF" + $"00170F000037000000000000003F173F0E0F0F0F0F0F0F00FFFF00000F0F0FFF" + $"00170F373600370000000000003F173F0E0F0F0F0F0F0F00FF000F0FFFFFFFFF" + $"00170F000000370036003700003F173F0E0F0F0F0F0F0F00FF000FFFFFFFFFFF" + $"00170F000000373637003700003F173F0E0F0F0F0F0F0F00FF000FFFFFFFFFFF" + $"00170F000000370036373700003F173F0E0F0F0F0F0F0F00FFFF000EFFFFFFFF" + $"00170F000000000037000036003F173F0E0F0F0F0F0F0F00FFFFFF000EFFFFFF" + $"00173F3F0000000037000000003F173F0E0F0F0F0F0F0F00FFFFFF000FFFFFFF" + $"001717183F3F000000000000003F173F0E0F0F0F0F0F0F000F0EFF000FFFFFFF" + $"FF00001717183F3F00000000003F173F0E0F0F0F0F0F0F000F0E000FFFFFFFFF" + $"FFFFFF00001717183F3F0000003F173F0E0F0F0F0F0F000F0F000FFFFFFFFFFF" + $"FFFFFFFFFF00001717183F3F003F173F0E0F0F0F0F000000000FFFFFFFFFFFFF" + $"FFFFFFFFFFFFFF00001717183F3F173F0E0F0F0F000F0F0F0FFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFF0000171718173F0E0F0F000F0F0FFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFF000017173F0E0F000F0F0FFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFF00003F0E000F0F0FFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000E0F0FFFFFFFFFFFFFFFFFFFFFFFFF" +}; + +resource mini_icon array { + $"FFFFFF0000FFFFFFFFFFFFFFFFFFFFFF" + $"FFFF001B1C0000FFFFFFFFFFFFFFFFFF" + $"FF001B1C1B1C1C0000FFFFFFFFFFFFFF" + $"003F1B1C1B1C1C1B1C0000FFFFFFFFFF" + $"00173F3F1B1C1B1C1C1B1C00FFFFFFFF" + $"000E18173F3F1B1C1B1C0F00FFFFFFFF" + $"000E000018173F3F1B0F0F00FFFFFFFF" + $"000E0000000018170F0F0F00FFFF0000" + $"000E3600370000180F0F0E00FF000E0E" + $"000E0036370000180F0F0E00FF000EFF" + $"000F0000363737180E0F0F00FF000EFF" + $"00170000370000170F0F0F00FF000FFF" + $"00001717000000180F0E0F0000000FFF" + $"FFFF0000171700180F0E0000000EFFFF" + $"FFFFFFFF000017170F000F0F0EFFFFFF" + $"FFFFFFFFFFFF0000000E0FFFFFFFFFFF" +}; + +#endif // HAIKU_TARGET_PLATFORM_HAIKU diff --git a/src/preferences/cpufrequency/main.cpp b/src/preferences/cpufrequency/main.cpp new file mode 100644 index 0000000000..284e70b03f --- /dev/null +++ b/src/preferences/cpufrequency/main.cpp @@ -0,0 +1,30 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#include "PreferencesWindow.h" +#include "CPUFrequencyView.h" +#include + + +int +main(int argc, char* argv[]) +{ + BApplication *app = new BApplication(kPrefSignature); + PreferencesWindow *window; + window = new PreferencesWindow("CPU Frequency", + kPreferencesFileName, + kDefaultPreferences); + CPUFrequencyView* prefView = new CPUFrequencyView(BRect(0, 0, 400, 350), + window); + window->SetPreferencesView(prefView); + window->Show(); + app->Run(); + + delete app; + return 0; +}