summaryrefslogtreecommitdiffstats
path: root/src/devices/backlight.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/backlight.cpp')
-rw-r--r--src/devices/backlight.cpp225
1 files changed, 225 insertions, 0 deletions
diff --git a/src/devices/backlight.cpp b/src/devices/backlight.cpp
new file mode 100644
index 0000000..c73e4c9
--- /dev/null
+++ b/src/devices/backlight.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <limits.h>
+
+
+using namespace std;
+
+#include "device.h"
+#include "backlight.h"
+#include "../parameters/parameters.h"
+
+#include <string.h>
+
+
+backlight::backlight(const char *_name, const char *path): device()
+{
+ min_level = 0;
+ max_level = 0;
+ start_level = 0;
+ end_level = 0;
+ pt_strcpy(sysfs_path, path);
+ register_sysfs_path(sysfs_path);
+ snprintf(name, sizeof(name) - 1, "backlight:%s", _name);
+ r_index = get_result_index(name);
+ r_index_power = 0;
+}
+
+void backlight::start_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "%s/max_brightness", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> max_level;
+ }
+ file.close();
+
+ snprintf(filename, sizeof(filename), "%s/actual_brightness", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_level;
+ file.close();
+ }
+}
+
+static int dpms_screen_on(void)
+{
+ DIR *dir;
+ struct dirent *entry;
+ char filename[PATH_MAX];
+ char line[4096];
+ ifstream file;
+
+ dir = opendir("/sys/class/drm/card0");
+ if (!dir)
+ return 1;
+ while (1) {
+ entry = readdir(dir);
+ if (!entry)
+ break;
+
+ if (strncmp(entry->d_name, "card", 4) != 0)
+ continue;
+ snprintf(filename, sizeof(filename), "/sys/class/drm/card0/%s/enabled", entry->d_name);
+ file.open(filename, ios::in);
+ if (!file)
+ continue;
+ file.getline(line, sizeof(line));
+ file.close();
+ if (strcmp(line, "enabled") != 0)
+ continue;
+ snprintf(filename, sizeof(filename), "/sys/class/drm/card0/%s/dpms", entry->d_name);
+ file.open(filename, ios::in);
+ if (!file)
+ continue;
+ file.getline(line, sizeof(line));
+ file.close();
+ if (strcmp(line, "On") == 0) {
+ closedir(dir);
+ return 1;
+ }
+ }
+ closedir(dir);
+ return 0;
+}
+
+void backlight::end_measurement(void)
+{
+ char filename[PATH_MAX];
+ char powername[4096];
+ ifstream file;
+ double p;
+ int _backlight = 0;
+
+ snprintf(filename, sizeof(filename), "%s/actual_brightness", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_level;
+ }
+ file.close();
+
+ if (dpms_screen_on()) {
+ p = 100.0 * (end_level + start_level) / 2 / max_level;
+ _backlight = 100;
+ } else {
+ p = 0;
+ }
+
+ report_utilization(name, p);
+ snprintf(powername, sizeof(powername), "%s-power", name);
+ report_utilization(powername, _backlight);
+}
+
+
+double backlight::utilization(void)
+{
+ double p;
+
+ p = 100.0 * (end_level + start_level) / 2 / max_level;
+ return p;
+}
+
+const char * backlight::device_name(void)
+{
+ return name;
+}
+
+static void create_all_backlights_callback(const char *d_name)
+{
+ class backlight *bl;
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof(filename), "/sys/class/backlight/%s", d_name);
+ bl = new class backlight(d_name, filename);
+ all_devices.push_back(bl);
+}
+
+void create_all_backlights(void)
+{
+ process_directory("/sys/class/backlight/", create_all_backlights_callback);
+ register_parameter("backlight");
+ register_parameter("backlight-power");
+ register_parameter("backlight-boost-40", 0, 0.5);
+ register_parameter("backlight-boost-80", 0, 0.5);
+ register_parameter("backlight-boost-100", 0, 0.5);
+}
+
+double backlight::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double _utilization;
+ char powername[4096];
+ static int bl_index = 0, blp_index = 0, bl_boost_index40 = 0, bl_boost_index80, bl_boost_index100;
+
+ if (!bl_index)
+ bl_index = get_param_index("backlight");
+ if (!blp_index)
+ blp_index = get_param_index("backlight-power");
+ if (!bl_boost_index40)
+ bl_boost_index40 = get_param_index("backlight-boost-40");
+ if (!bl_boost_index80)
+ bl_boost_index80 = get_param_index("backlight-boost-80");
+ if (!bl_boost_index100)
+ bl_boost_index100 = get_param_index("backlight-boost-100");
+
+ power = 0;
+ factor = get_parameter_value(bl_index, bundle);
+ _utilization = get_result_value(r_index, result);
+
+ power += _utilization * factor / 100.0;
+
+ /*
+ * most machines have a non-linear backlight scale. to compensate, add a fixed value
+ * once the brightness hits 40% and 80%
+ */
+
+ if (_utilization >=99)
+ power += get_parameter_value(bl_boost_index100, bundle);
+ else if (_utilization >=80)
+ power += get_parameter_value(bl_boost_index80, bundle);
+ else if (_utilization >=40)
+ power += get_parameter_value(bl_boost_index40, bundle);
+
+ factor = get_parameter_value(blp_index, bundle);
+
+ if (!r_index_power) {
+ sprintf(powername, "%s-power", name);
+ r_index_power = get_result_index(powername);
+ }
+ _utilization = get_result_value(r_index_power, result);
+
+ power += _utilization * factor / 100.0;
+
+ return power;
+}