From d5c86902432529996ef5ac12cb7721a18516b000 Mon Sep 17 00:00:00 2001 From: Aaron Plattner Date: Mon, 1 Jul 2013 08:51:18 -0700 Subject: 319.32 --- doc/version.mk | 2 +- samples/version.mk | 2 +- src/gtk+-2.x/ctkcolorcontrols.c | 34 +- src/gtk+-2.x/ctkcolorcontrols.h | 1 + src/gtk+-2.x/ctkditheringcontrols.c | 28 +- src/gtk+-2.x/ctkditheringcontrols.h | 2 + src/gtk+-2.x/ctkevent.c | 3 +- src/gtk+-2.x/ctkpowermizer.c | 672 ++++++++++++++++++++++++++++-------- src/gtk+-2.x/ctkpowermizer.h | 8 +- src/libXNVCtrl/NVCtrl.h | 89 +++-- src/parse.c | 3 +- src/version.mk | 2 +- version.mk | 2 +- 13 files changed, 667 insertions(+), 181 deletions(-) diff --git a/doc/version.mk b/doc/version.mk index 6b57a0b..47298b6 100644 --- a/doc/version.mk +++ b/doc/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 319.23 +NVIDIA_VERSION = 319.32 diff --git a/samples/version.mk b/samples/version.mk index 6b57a0b..47298b6 100644 --- a/samples/version.mk +++ b/samples/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 319.23 +NVIDIA_VERSION = 319.32 diff --git a/src/gtk+-2.x/ctkcolorcontrols.c b/src/gtk+-2.x/ctkcolorcontrols.c index 97b5d87..913e0e7 100644 --- a/src/gtk+-2.x/ctkcolorcontrols.c +++ b/src/gtk+-2.x/ctkcolorcontrols.c @@ -35,6 +35,11 @@ #include "ctkdropdownmenu.h" /* function prototypes */ +static void +ctk_color_controls_class_init(CtkColorControlsClass *ctk_object_class); + +static void ctk_color_controls_finalize(GObject *object); + static gboolean build_color_space_table(CtkColorControls *ctk_color_controls, NVCTRLAttributeValidValuesRec valid); @@ -87,7 +92,7 @@ GType ctk_color_controls_get_type(void) sizeof (CtkColorControlsClass), NULL, /* base_init */ NULL, /* base_finalize */ - NULL, /* class_init, */ + (GClassInitFunc) ctk_color_controls_class_init, /* class_init, */ NULL, /* class_finalize */ NULL, /* class_data */ sizeof (CtkColorControls), @@ -105,6 +110,32 @@ GType ctk_color_controls_get_type(void) return ctk_color_controls_type; } /* ctk_color_controls_get_type() */ + + +static void +ctk_color_controls_class_init(CtkColorControlsClass *ctk_object_class) +{ + GObjectClass *gobject_class = (GObjectClass *)ctk_object_class; + gobject_class->finalize = ctk_color_controls_finalize; +} + + + +static void ctk_color_controls_finalize(GObject *object) +{ + CtkColorControls *ctk_object = CTK_COLOR_CONTROLS(object); + + g_signal_handlers_disconnect_matched(G_OBJECT(ctk_object->ctk_event), + G_SIGNAL_MATCH_DATA, + 0, + 0, + NULL, + NULL, + (gpointer) ctk_object); +} + + + GtkWidget* ctk_color_controls_new(NvCtrlAttributeHandle *handle, CtkConfig *ctk_config, CtkEvent *ctk_event, @@ -141,6 +172,7 @@ GtkWidget* ctk_color_controls_new(NvCtrlAttributeHandle *handle, ctk_color_controls = CTK_COLOR_CONTROLS(object); ctk_color_controls->handle = handle; ctk_color_controls->ctk_config = ctk_config; + ctk_color_controls->ctk_event = ctk_event; ctk_color_controls->reset_button = reset_button; ctk_color_controls->name = strdup(name); diff --git a/src/gtk+-2.x/ctkcolorcontrols.h b/src/gtk+-2.x/ctkcolorcontrols.h index cdfd233..8888af0 100644 --- a/src/gtk+-2.x/ctkcolorcontrols.h +++ b/src/gtk+-2.x/ctkcolorcontrols.h @@ -54,6 +54,7 @@ struct _CtkColorControls NvCtrlAttributeHandle *handle; CtkConfig *ctk_config; + CtkEvent *ctk_event; GtkWidget *reset_button; GtkWidget *color_controls_box; diff --git a/src/gtk+-2.x/ctkditheringcontrols.c b/src/gtk+-2.x/ctkditheringcontrols.c index f8204de..46431c9 100644 --- a/src/gtk+-2.x/ctkditheringcontrols.c +++ b/src/gtk+-2.x/ctkditheringcontrols.c @@ -35,6 +35,11 @@ #include "ctkdropdownmenu.h" /* function prototypes */ +static void +ctk_dither_controls_class_init(CtkDitheringControlsClass *ctk_object_class); + +static void ctk_dither_controls_finalize(GObject *object); + static gboolean build_dithering_mode_table(CtkDitheringControls *ctk_dithering_controls); static gint map_nvctrl_value_to_table(CtkDitheringControls *ctk_dithering_controls, @@ -107,7 +112,7 @@ GType ctk_dithering_controls_get_type(void) sizeof (CtkDitheringControlsClass), NULL, /* base_init */ NULL, /* base_finalize */ - NULL, /* class_init, */ + (GClassInitFunc) ctk_dither_controls_class_init, /* class_init, */ NULL, /* class_finalize */ NULL, /* class_data */ sizeof (CtkDitheringControls), @@ -125,6 +130,26 @@ GType ctk_dithering_controls_get_type(void) return ctk_dithering_controls_type; } /* ctk_dithering_controls_get_type() */ +static void +ctk_dither_controls_class_init(CtkDitheringControlsClass *ctk_object_class) +{ + GObjectClass *gobject_class = (GObjectClass *)ctk_object_class; + gobject_class->finalize = ctk_dither_controls_finalize; +} + +static void ctk_dither_controls_finalize(GObject *object) +{ + CtkDitheringControls *ctk_object = CTK_DITHERING_CONTROLS(object); + + g_signal_handlers_disconnect_matched(G_OBJECT(ctk_object->ctk_event), + G_SIGNAL_MATCH_DATA, + 0, + 0, + NULL, + NULL, + (gpointer) ctk_object); +} + GtkWidget* ctk_dithering_controls_new(NvCtrlAttributeHandle *handle, CtkConfig *ctk_config, CtkEvent *ctk_event, @@ -153,6 +178,7 @@ GtkWidget* ctk_dithering_controls_new(NvCtrlAttributeHandle *handle, ctk_dithering_controls = CTK_DITHERING_CONTROLS(object); ctk_dithering_controls->handle = handle; + ctk_dithering_controls->ctk_event = ctk_event; ctk_dithering_controls->ctk_config = ctk_config; ctk_dithering_controls->reset_button = reset_button; ctk_dithering_controls->name = strdup(name); diff --git a/src/gtk+-2.x/ctkditheringcontrols.h b/src/gtk+-2.x/ctkditheringcontrols.h index f87ac9c..4cb00b8 100644 --- a/src/gtk+-2.x/ctkditheringcontrols.h +++ b/src/gtk+-2.x/ctkditheringcontrols.h @@ -57,6 +57,8 @@ struct _CtkDitheringControls char *name; GtkWidget *reset_button; + CtkEvent *ctk_event; + GtkWidget *dithering_controls_box; GtkWidget *dithering_mode_box; GtkWidget *dithering_depth_box; diff --git a/src/gtk+-2.x/ctkevent.c b/src/gtk+-2.x/ctkevent.c index 40054c0..0cc1cd1 100644 --- a/src/gtk+-2.x/ctkevent.c +++ b/src/gtk+-2.x/ctkevent.c @@ -326,6 +326,7 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_SIGNAL(NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_IMMEDIATE); MAKE_SIGNAL(NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_REBOOT); MAKE_SIGNAL(NV_CTRL_DPY_HDMI_3D); + MAKE_SIGNAL(NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE); #undef MAKE_SIGNAL /* @@ -335,7 +336,7 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) * knows about. */ -#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_DPY_HDMI_3D +#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE #warning "There are attributes that do not emit signals!" #endif diff --git a/src/gtk+-2.x/ctkpowermizer.c b/src/gtk+-2.x/ctkpowermizer.c index a900c5c..d4c8208 100644 --- a/src/gtk+-2.x/ctkpowermizer.c +++ b/src/gtk+-2.x/ctkpowermizer.c @@ -49,17 +49,6 @@ static void dp_configuration_update_received(GtkObject *, gpointer, gpointer); static void post_dp_configuration_update(CtkPowermizer *); static void show_dp_toggle_warning_dlg(CtkPowermizer *ctk_powermizer); -typedef struct { - const char *label; - int attr; -} PowerMizerMode; - -PowerMizerMode __powermizer_modes[] = -{ - { "Adaptive", NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE }, - { "Prefer Maximum Performance", NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_MAXIMUM_PERFORMANCE }, -}; - static const char *__adaptive_clock_help = "The Adaptive Clocking status describes if this feature " "is currently enabled in this GPU."; @@ -97,11 +86,24 @@ static const char *__performance_levels_table_help = static const char *__powermizer_menu_help = "The Preferred Mode menu allows you to choose the preferred Performance " "State for the GPU, provided the GPU has multiple Performance Levels. " +"If a single X server is running, the mode selected in nvidia-settings is what " +"the system will be using; if two or more X servers are running, the behavior " +"is undefined. "; + +static const char *__powermizer_auto_mode_help = +"'Auto' mode lets the driver choose the best Performance State for your GPU. "; + +static const char *__powermizer_adaptive_mode_help = "'Adaptive' mode allows the GPU clocks to be adjusted based on GPU " -"utilization. 'Prefer Maximum Performance' hints to the driver to prefer " -"higher GPU clocks, when possible. If a single X server is running, the " -"mode selected in nvidia-settings is what the system will be using; if two or " -"more X servers are running, the behavior is undefined."; +"utilization. "; + +static const char *__powermizer_prefer_maximum_performance_help = +"'Prefer Maximum Performance' hints to the driver to prefer higher GPU clocks, " +"when possible. "; + +static const char *__powermizer_prefer_consistent_performance_help = +"'Prefer Consistent Performance' hints to the driver to lock to GPU base clocks, " +"when possible. "; static const char *__dp_configuration_button_help = "CUDA - Double Precision lets you enable " @@ -144,6 +146,12 @@ typedef struct { gint nvclock; gint memclock; gint processorclock; + gint nvclockmin; + gint nvclockmax; + gint memclockmin; + gint memclockmax; + gint processorclockmin; + gint processorclockmax; } perfModeEntry, * perfModeEntryPtr; @@ -155,10 +163,22 @@ static void apply_perf_mode_token(char *token, char *value, void *data) pEntry->perf_level = atoi(value); } else if (!strcasecmp("nvclock", token)) { pEntry->nvclock = atoi(value); + } else if (!strcasecmp("nvclockmin", token)) { + pEntry->nvclockmin = atoi(value); + } else if (!strcasecmp("nvclockmax", token)) { + pEntry->nvclockmax = atoi(value); } else if (!strcasecmp("memclock", token)) { pEntry->memclock = atoi(value); + } else if (!strcasecmp("memclockmin", token)) { + pEntry->memclockmin = atoi(value); + } else if (!strcasecmp("memclockmax", token)) { + pEntry->memclockmax = atoi(value); } else if (!strcasecmp("processorclock", token)) { pEntry->processorclock = atoi(value); + } else if (!strcasecmp("processorclockmin", token)) { + pEntry->processorclockmin = atoi(value); + } else if (!strcasecmp("processorclockmax", token)) { + pEntry->processorclockmax = atoi(value); } else { nv_warning_msg("Unknown Perf Mode token value pair: %s=%s", token, value); @@ -172,97 +192,322 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, GtkWidget *table; GtkWidget *label; char *perf_modes = NULL; + char *tmp_perf_modes = NULL; char *tokens; char tmp_str[24]; - perfModeEntry entry; gint ret; - gint row_idx; /* Where to insert into the perf mode table */ + gint row_idx = 0; /* Where to insert into the perf mode table */ gboolean active; + GtkWidget *vsep; + perfModeEntryPtr pEntry = NULL; + perfModeEntryPtr tmpEntry = NULL; + gint index = 0; + gint i = 0; + + /* Get the current list of perf levels */ + + ret = NvCtrlGetStringAttribute(ctk_powermizer->attribute_handle, + NV_CTRL_STRING_PERFORMANCE_MODES, + &perf_modes); + + if (ret != NvCtrlSuccess) { + /* Bail */ + return; + } + + /* Calculate the number of rows we needed vseparator in the table */ + tmp_perf_modes = g_strdup(perf_modes); + for (tokens = strtok(tmp_perf_modes, ";"); + tokens; + tokens = strtok(NULL, ";")) { + + tmpEntry = realloc(pEntry, sizeof(*pEntry) * (index + 1)); + + if (!tmpEntry) { + continue; + } + pEntry = tmpEntry; + tmpEntry = NULL; + + /* Invalidate perf mode entry */ + memset(pEntry + index, -1, sizeof(*pEntry)); + + parse_token_value_pairs(tokens, apply_perf_mode_token, + (void *) &pEntry[index]); + + /* Only add complete perf mode entries */ + if ((pEntry[index].perf_level != -1) && + (pEntry[index].nvclockmax != -1) && + (pEntry[index].memclockmax != -1)) { + /* Set hasDecoupledClocks flag to decide new/old clock + * interface to show. + */ + if (!ctk_powermizer->hasDecoupledClock && + ((pEntry[index].nvclockmax != pEntry[index].nvclockmin) || + (pEntry[index].memclockmax != pEntry[index].memclockmin) || + (pEntry[index].processorclockmax != + pEntry[index].processorclockmin))) { + ctk_powermizer->hasDecoupledClock = TRUE; + } + row_idx++; + } + index++; + } + g_free(tmp_perf_modes); /* Since table cell management in GTK lacks, just remove and rebuild * the table from scratch. */ - + /* Dump out the old table */ ctk_empty_container(ctk_powermizer->performance_table_hbox); /* Generate a new table */ - table = gtk_table_new(1, 4, FALSE); - gtk_table_set_row_spacings(GTK_TABLE(table), 3); - gtk_table_set_col_spacings(GTK_TABLE(table), 15); - gtk_container_set_border_width(GTK_CONTAINER(table), 5); + if (ctk_powermizer->hasDecoupledClock) { + table = gtk_table_new(2, 15, FALSE); + row_idx = row_idx + 3; + gtk_table_set_row_spacings(GTK_TABLE(table), 3); + gtk_table_set_col_spacings(GTK_TABLE(table), 15); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); - gtk_box_pack_start(GTK_BOX(ctk_powermizer->performance_table_hbox), - table, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(ctk_powermizer->performance_table_hbox), + table, FALSE, FALSE, 0); - if (ctk_powermizer->performance_level) { - label = gtk_label_new("Performance Level"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } + if (ctk_powermizer->performance_level) { + label = gtk_label_new("Level"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + + /* Vertical separator */ + vsep = gtk_vseparator_new(); + gtk_table_attach(GTK_TABLE(table), vsep, 1, 2, 0, row_idx, + GTK_FILL, GTK_FILL | GTK_EXPAND, 0, 0); + } - if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) { - label = gtk_label_new("Graphics Clock"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 1, 2, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) { + /* Graphics clock */ + label = gtk_label_new("Graphics Clock"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 2, 5, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Current"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 2, 3, 1, 2, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Min"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 3, 4, 1, 2, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Max"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 4, 5, 1, 2, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("Memory Clock"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } + /* Vertical separator */ + vsep = gtk_vseparator_new(); + gtk_table_attach(GTK_TABLE(table), vsep, 5, 6, 0, row_idx, + GTK_FILL, GTK_FILL | GTK_EXPAND, 0, 0); + + /* Memory clock */ + label = gtk_label_new("Memory Clock"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 6, 9, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Current"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 6, 7, 1, 2, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Min"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 7, 8, 1, 2, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Max"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 8, 9, 1, 2, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + + /* Vertical separator */ + vsep = gtk_vseparator_new(); + gtk_table_attach(GTK_TABLE(table), vsep, 9, 10, 0, row_idx, + GTK_FILL, GTK_FILL | GTK_EXPAND, 0, 0); + } + if (ctk_powermizer->processor_clock) { + /* Processor clock */ + label = gtk_label_new("Processor Clock"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 10, 11, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Current"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 11, 12, 1, 2, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Min"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 12, 13, 1, 2, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Max"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 13, 14, 1, 2, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + + /* Vertical separator */ + vsep = gtk_vseparator_new(); + gtk_table_attach(GTK_TABLE(table), vsep, 14, 15, 0, row_idx, + GTK_FILL, GTK_FILL | GTK_EXPAND, 0, 0); + } + } else { - if (ctk_powermizer->processor_clock) { - label = gtk_label_new("Processor Clock"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 3, 4, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } - /* Get the current list of perf levels */ + table = gtk_table_new(1, 4, FALSE); + gtk_table_set_row_spacings(GTK_TABLE(table), 3); + gtk_table_set_col_spacings(GTK_TABLE(table), 15); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); - ret = NvCtrlGetStringAttribute(ctk_powermizer->attribute_handle, - NV_CTRL_STRING_PERFORMANCE_MODES, - &perf_modes); + gtk_box_pack_start(GTK_BOX(ctk_powermizer->performance_table_hbox), + table, FALSE, FALSE, 0); - if (ret != NvCtrlSuccess) { - gtk_widget_show_all(table); - /* Bail */ - return; + if (ctk_powermizer->performance_level) { + label = gtk_label_new("Performance Level"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } + + if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) { + label = gtk_label_new("Graphics Clock"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 1, 2, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + + + label = gtk_label_new("Memory Clock"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } + + if (ctk_powermizer->processor_clock) { + label = gtk_label_new("Processor Clock"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 3, 4, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } } /* Parse the perf levels and populate the table */ + row_idx = 0; //reset value used to calculate vseparator. + row_idx = 3; + for (i = 0; i < index; i++) { + /* Only add complete perf mode entries */ + if (ctk_powermizer->hasDecoupledClock && + (pEntry[i].perf_level != -1) && + (pEntry[i].nvclockmax != -1) && + (pEntry[i].memclockmax != -1)) { - row_idx = 1; - for (tokens = strtok(perf_modes, ";"); - tokens; - tokens = strtok(NULL, ";")) { + active = (pEntry[i].perf_level == perf_level); - /* Invalidate perf mode entry */ - entry.perf_level = -1; - entry.nvclock = -1; - entry.memclock = -1; - entry.processorclock = -1; - - parse_token_value_pairs(tokens, apply_perf_mode_token, - &entry); - - /* Only add complete perf mode entries */ - if ((entry.perf_level != -1) && - (entry.nvclock != -1) && - (entry.memclock != -1)) { - - active = (entry.perf_level == perf_level); + /* XXX Assume the perf levels are sorted by the server */ + + gtk_table_resize(GTK_TABLE(table), row_idx+1, 10); + + if (ctk_powermizer->performance_level) { + g_snprintf(tmp_str, 24, "%d", pEntry[i].perf_level); + label = gtk_label_new(tmp_str); + gtk_widget_set_sensitive(label, active); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, + row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } + + if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) { + if (active) { + g_snprintf(tmp_str, 24, "%d MHz", ctk_powermizer->nvclock); + label = gtk_label_new(tmp_str); + gtk_widget_set_sensitive(label, active); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 2, 3, + row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } + g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].nvclockmin); + label = gtk_label_new(tmp_str); + gtk_widget_set_sensitive(label, active); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 3, 4, + row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].nvclockmax); + label = gtk_label_new(tmp_str); + gtk_widget_set_sensitive(label, active); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 4, 5, + row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + + if (active) { + g_snprintf(tmp_str, 24, "%d MHz", ctk_powermizer->memclock); + label = gtk_label_new(tmp_str); + gtk_widget_set_sensitive(label, active); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 6, 7, + row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } + g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].memclockmin); + label = gtk_label_new(tmp_str); + gtk_widget_set_sensitive(label, active); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 7, 8, + row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].memclockmax); + label = gtk_label_new(tmp_str); + gtk_widget_set_sensitive(label, active); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 8, 9, + row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } + if (ctk_powermizer->processor_clock) { + if (active) { + g_snprintf(tmp_str, 24, "%d MHz", ctk_powermizer->processorclock); + label = gtk_label_new(tmp_str); + gtk_widget_set_sensitive(label, active); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 11, 12, row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } + g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].processorclockmin); + label = gtk_label_new(tmp_str); + gtk_widget_set_sensitive(label, active); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 12, 13, + row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].processorclockmax); + label = gtk_label_new(tmp_str); + gtk_widget_set_sensitive(label, active); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 13, 14, + row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } + row_idx++; + } else if ((pEntry[i].perf_level != -1) && + (pEntry[i].nvclock != -1) && + (pEntry[i].memclock != -1)) { + + active = (pEntry[i].perf_level == perf_level); /* XXX Assume the perf levels are sorted by the server */ - gtk_table_resize(GTK_TABLE(table), row_idx+1, 4); + gtk_table_resize(GTK_TABLE(table), row_idx+1, 10); if (ctk_powermizer->performance_level) { - g_snprintf(tmp_str, 24, "%d", entry.perf_level); + g_snprintf(tmp_str, 24, "%d", pEntry[i].perf_level); label = gtk_label_new(tmp_str); gtk_widget_set_sensitive(label, active); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); @@ -272,7 +517,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, } if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) { - g_snprintf(tmp_str, 24, "%d MHz", entry.nvclock); + g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].nvclock); label = gtk_label_new(tmp_str); gtk_widget_set_sensitive(label, active); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); @@ -280,7 +525,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, row_idx, row_idx+1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - g_snprintf(tmp_str, 24, "%d MHz", entry.memclock); + g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].memclock); label = gtk_label_new(tmp_str); gtk_widget_set_sensitive(label, active); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); @@ -289,7 +534,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); } if (ctk_powermizer->processor_clock) { - g_snprintf(tmp_str, 24, "%d MHz", entry.processorclock); + g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].processorclock); label = gtk_label_new(tmp_str); gtk_widget_set_sensitive(label, active); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); @@ -300,14 +545,16 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, } else { nv_warning_msg("Incomplete Perf Mode (perf=%d, nvclock=%d," " memclock=%d)", - entry.perf_level, entry.nvclock, - entry.memclock); + pEntry[i].perf_level, pEntry[i].nvclock, + pEntry[i].memclock); } } gtk_widget_show_all(table); XFree(perf_modes); + XFree(pEntry); + pEntry = NULL; } @@ -351,6 +598,9 @@ static gboolean update_powermizer_info(gpointer user_data) memory_clock = clockret & 0x0000FFFF; gpu_clock = (clockret >> 16); + ctk_powermizer->nvclock = gpu_clock; + ctk_powermizer->memclock = memory_clock; + s = g_strdup_printf("%d Mhz", gpu_clock); gtk_label_set_text(GTK_LABEL(ctk_powermizer->gpu_clock), s); g_free(s); @@ -364,6 +614,7 @@ static gboolean update_powermizer_info(gpointer user_data) NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS, &processor_clock); if (ret == NvCtrlSuccess && ctk_powermizer->processor_clock) { + ctk_powermizer->processorclock = processor_clock; s = g_strdup_printf("%d Mhz", processor_clock); gtk_label_set_text(GTK_LABEL(ctk_powermizer->processor_clock), s); g_free(s); @@ -415,9 +666,83 @@ static gboolean update_powermizer_info(gpointer user_data) update_perf_mode_table(ctk_powermizer, perf_level); } + update_powermizer_menu_info(ctk_powermizer); + return TRUE; } + + +static gchar* get_powermizer_menu_label(const unsigned int val) +{ + gchar *label = NULL; + + switch (val) { + case NV_CTRL_GPU_POWER_MIZER_MODE_AUTO: + label = g_strdup_printf("Auto"); + break; + case NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE: + label = g_strdup_printf("Adaptive"); + break; + case NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_MAXIMUM_PERFORMANCE: + label = g_strdup_printf("Prefer Maximum Performance"); + break; + case NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_CONSISTENT_PERFORMANCE: + label = g_strdup_printf("Prefer Consistent Performance"); + break; + default: + label = g_strdup_printf(""); + break; + } + + return label; +} + + + +static gchar* get_powermizer_help_text(const unsigned int bit_mask) +{ + const gboolean bAuto = + bit_mask & (1 << NV_CTRL_GPU_POWER_MIZER_MODE_AUTO); + const gboolean bAdaptive = + bit_mask & (1 << NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE); + const gboolean bMaximum = + bit_mask & (1 << NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_MAXIMUM_PERFORMANCE); + const gboolean bConsistent = + bit_mask & (1 << NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_CONSISTENT_PERFORMANCE); + + gchar *text = NULL; + + text = + g_strdup_printf("%s%s%s%s%s", + __powermizer_menu_help, + bAuto ? __powermizer_auto_mode_help : "", + bAdaptive ? __powermizer_adaptive_mode_help : "", + bMaximum ? __powermizer_prefer_maximum_performance_help : "", + bConsistent ? __powermizer_prefer_consistent_performance_help : ""); + + return text; +} + + +static void create_powermizer_menu_entry(CtkDropDownMenu *menu, + const unsigned int bit_mask, + const unsigned int val) +{ + gchar *label; + + if (!(bit_mask & (1 << val))) { + return; + } + + label = get_powermizer_menu_label(val); + + ctk_drop_down_menu_append_item(menu, label, val); + g_free(label); +} + + + GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, CtkConfig *ctk_config, CtkEvent *ctk_event) @@ -433,7 +758,6 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, gint row = 0; gchar *s = NULL; gint tmp; - gint i; gboolean processor_clock_available = FALSE; gboolean power_source_available = FALSE; gboolean perf_level_available = FALSE; @@ -441,11 +765,12 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, gboolean clock_freqs_available = FALSE; gboolean cuda_dp_ui = FALSE; gboolean pcie_gen_queriable = FALSE; + NVCTRLAttributeValidValuesRec valid_modes; /* make sure we have a handle */ g_return_val_if_fail(handle != NULL, NULL); - + /* check if this screen supports powermizer querying */ ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_POWER_SOURCE, &val); @@ -483,7 +808,7 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, if (ret == NvCtrlSuccess) { pcie_gen_queriable = TRUE; } - + /* return early if query to attributes fail */ if (!power_source_available && !perf_level_available && !adaptive_clock_state_available && clock_freqs_available && @@ -493,11 +818,12 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, /* create the CtkPowermizer object */ object = g_object_new(CTK_TYPE_POWERMIZER, NULL); - + ctk_powermizer = CTK_POWERMIZER(object); ctk_powermizer->attribute_handle = handle; ctk_powermizer->ctk_config = ctk_config; ctk_powermizer->pcie_gen_queriable = pcie_gen_queriable; + ctk_powermizer->hasDecoupledClock = FALSE; /* set container properties for the CtkPowermizer widget */ @@ -687,7 +1013,7 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, s = g_strdup_printf("PowerMizer Monitor (GPU %d)", NvCtrlGetTargetId(handle)); - + ctk_config_add_timer(ctk_powermizer->ctk_config, DEFAULT_UPDATE_POWERMIZER_INFO_TIME_INTERVAL, s, @@ -697,65 +1023,103 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, /* PowerMizer Settings */ - hbox = gtk_hbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + ret = NvCtrlGetValidAttributeValues(ctk_powermizer->attribute_handle, + NV_CTRL_GPU_POWER_MIZER_MODE, + &valid_modes); - vbox2 = gtk_vbox_new(FALSE, 5); - gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0); - ctk_powermizer->box_powermizer_menu = vbox2; + if ((ret == NvCtrlSuccess) && + (valid_modes.type == ATTRIBUTE_TYPE_INT_BITS)) { + const unsigned int bit_mask = valid_modes.u.bits.ints; - /* H-separator */ + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - hbox2 = gtk_hbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, 0); + vbox2 = gtk_vbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0); - label = gtk_label_new("PowerMizer Settings"); - gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); + ctk_powermizer->box_powermizer_menu = vbox2; - hsep = gtk_hseparator_new(); - gtk_box_pack_start(GTK_BOX(hbox2), hsep, TRUE, TRUE, 5); + /* H-separator */ - /* Specifying drop down list */ + hbox2 = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, 0); - menu = (CtkDropDownMenu *) - ctk_drop_down_menu_new(CTK_DROP_DOWN_MENU_FLAG_COMBO); + label = gtk_label_new("PowerMizer Settings"); + gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); - for (i=0; i < ARRAY_LEN(__powermizer_modes); i++) { - ctk_drop_down_menu_append_item(menu, __powermizer_modes[i].label, i); - } + hsep = gtk_hseparator_new(); + gtk_box_pack_start(GTK_BOX(hbox2), hsep, TRUE, TRUE, 5); + + /* Specifying drop down list */ + + menu = (CtkDropDownMenu *) + ctk_drop_down_menu_new(CTK_DROP_DOWN_MENU_FLAG_COMBO); + + create_powermizer_menu_entry( + menu, bit_mask, + NV_CTRL_GPU_POWER_MIZER_MODE_AUTO); + create_powermizer_menu_entry( + menu, bit_mask, + NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE); + create_powermizer_menu_entry( + menu, bit_mask, + NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_MAXIMUM_PERFORMANCE); + create_powermizer_menu_entry( + menu, bit_mask, + NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_CONSISTENT_PERFORMANCE); + + ctk_powermizer->powermizer_menu = GTK_WIDGET(menu); + + g_signal_connect(G_OBJECT(ctk_powermizer->powermizer_menu), "changed", + G_CALLBACK(powermizer_menu_changed), + (gpointer) ctk_powermizer); - ctk_powermizer->powermizer_menu = GTK_WIDGET(menu); - update_powermizer_menu_info(ctk_powermizer); + ctk_powermizer->powermizer_menu_help = + get_powermizer_help_text(bit_mask); - g_signal_connect(G_OBJECT(ctk_powermizer->powermizer_menu), "changed", - G_CALLBACK(powermizer_menu_changed), - (gpointer) ctk_powermizer); + ctk_config_set_tooltip(ctk_config, + ctk_powermizer->powermizer_menu, + ctk_powermizer->powermizer_menu_help); + + /* Packing the drop down list */ + + table = gtk_table_new(1, 4, FALSE); + gtk_box_pack_start(GTK_BOX(vbox2), table, FALSE, FALSE, 0); + gtk_table_set_row_spacings(GTK_TABLE(table), 3); + gtk_table_set_col_spacings(GTK_TABLE(table), 0); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + + hbox2 = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox2, 0, 1, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Preferred Mode:"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); - ctk_config_set_tooltip(ctk_config, + hbox2 = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox2, 1, 2, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + gtk_box_pack_start(GTK_BOX(hbox2), ctk_powermizer->powermizer_menu, - __powermizer_menu_help); + FALSE, FALSE, 0); - /* Packing the drop down list */ + hbox2 = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox2, 2, 3, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Current Mode:"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); - table = gtk_table_new(1, 2, FALSE); - gtk_box_pack_start(GTK_BOX(vbox2), table, FALSE, FALSE, 0); - gtk_table_set_row_spacings(GTK_TABLE(table), 3); - gtk_table_set_col_spacings(GTK_TABLE(table), 15); - gtk_container_set_border_width(GTK_CONTAINER(table), 5); - - hbox2 = gtk_hbox_new(FALSE, 0); - gtk_table_attach(GTK_TABLE(table), hbox2, 0, 1, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("Preferred Mode:"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); - - hbox2 = gtk_hbox_new(FALSE, 0); - gtk_table_attach(GTK_TABLE(table), hbox2, 1, 2, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - gtk_box_pack_start(GTK_BOX(hbox2), - ctk_powermizer->powermizer_menu, - FALSE, FALSE, 0); + hbox2 = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox2, 3, 4, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new(""); + ctk_powermizer->powermizer_txt = label; + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); + + update_powermizer_menu_info(ctk_powermizer); + } /* * check if CUDA - Double Precision Boost support available. @@ -883,30 +1247,41 @@ static void update_powermizer_menu_event(GtkObject *object, static void update_powermizer_menu_info(gpointer user_data) { CtkPowermizer *ctk_powermizer = CTK_POWERMIZER(user_data); - gint powerMizerMode = NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE; - NVCTRLAttributeValidValuesRec valid; - ReturnStatus ret0, ret1; + gint powerMizerMode, defaultPowerMizerMode, actualPowerMizerMode; + + gchar* label; + ReturnStatus ret1, ret2; CtkDropDownMenu *menu; menu = CTK_DROP_DOWN_MENU(ctk_powermizer->powermizer_menu); - ret0 = NvCtrlGetValidAttributeValues(ctk_powermizer->attribute_handle, - NV_CTRL_GPU_POWER_MIZER_MODE, - &valid); - ret1 = NvCtrlGetAttribute(ctk_powermizer->attribute_handle, - NV_CTRL_GPU_POWER_MIZER_MODE, - &powerMizerMode); + NV_CTRL_GPU_POWER_MIZER_MODE, + &powerMizerMode); - if ((ret0 != NvCtrlSuccess) || (ret1 != NvCtrlSuccess)) { + ret2 = NvCtrlGetAttribute(ctk_powermizer->attribute_handle, + NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE, + &defaultPowerMizerMode); + + if ((ret1 != NvCtrlSuccess) || (ret2 != NvCtrlSuccess)) { gtk_widget_hide(ctk_powermizer->box_powermizer_menu); } else { g_signal_handlers_block_by_func(G_OBJECT(ctk_powermizer->powermizer_menu), G_CALLBACK(powermizer_menu_changed), (gpointer) ctk_powermizer); + if (powerMizerMode == NV_CTRL_GPU_POWER_MIZER_MODE_AUTO) { + actualPowerMizerMode = defaultPowerMizerMode; + } else { + actualPowerMizerMode = powerMizerMode; + } + ctk_drop_down_menu_set_current_value(menu, powerMizerMode); + label = get_powermizer_menu_label(actualPowerMizerMode); + gtk_label_set_text(GTK_LABEL(ctk_powermizer->powermizer_txt), label); + g_free(label); + g_signal_handlers_unblock_by_func(G_OBJECT(ctk_powermizer->powermizer_menu), G_CALLBACK(powermizer_menu_changed), (gpointer) ctk_powermizer); @@ -919,23 +1294,28 @@ static void powermizer_menu_changed(GtkWidget *widget, gpointer user_data) { CtkPowermizer *ctk_powermizer; - gint history, powerMizerMode = NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE; + guint powerMizerMode; CtkDropDownMenu *menu = CTK_DROP_DOWN_MENU(widget); - ctk_powermizer = CTK_POWERMIZER(user_data); + const char *label = ctk_drop_down_menu_get_current_name(menu); - history = ctk_drop_down_menu_get_current_value(menu); + ctk_powermizer = CTK_POWERMIZER(user_data); - powerMizerMode = __powermizer_modes[history].attr; + powerMizerMode = ctk_drop_down_menu_get_current_value(menu); if (NvCtrlSuccess != NvCtrlSetAttribute(ctk_powermizer->attribute_handle, NV_CTRL_GPU_POWER_MIZER_MODE, powerMizerMode)) { + ctk_config_statusbar_message(ctk_powermizer->ctk_config, + "Unable to set Preferred Mode to %s.", + label); return; } ctk_config_statusbar_message(ctk_powermizer->ctk_config, "Preferred Mode set to %s.", - __powermizer_modes[history].label); + label); + + update_powermizer_menu_info(user_data); } @@ -1153,7 +1533,7 @@ GtkTextBuffer *ctk_powermizer_create_help(GtkTextTagTable *table, if (ctk_powermizer->powermizer_menu) { ctk_help_heading(b, &i, "PowerMizer Settings"); - ctk_help_para(b, &i, __powermizer_menu_help); + ctk_help_para(b, &i, ctk_powermizer->powermizer_menu_help); } if (ctk_powermizer->configuration_button) { diff --git a/src/gtk+-2.x/ctkpowermizer.h b/src/gtk+-2.x/ctkpowermizer.h index adb179f..e1919e8 100644 --- a/src/gtk+-2.x/ctkpowermizer.h +++ b/src/gtk+-2.x/ctkpowermizer.h @@ -62,13 +62,19 @@ struct _CtkPowermizer GtkWidget *performance_level; GtkWidget *performance_table_hbox; GtkWidget *powermizer_menu; + GtkWidget *powermizer_txt; GtkWidget *box_powermizer_menu; + gchar *powermizer_menu_help; + GtkWidget *configuration_button; gboolean dp_enabled; gboolean dp_toggle_warning_dlg_shown; + gboolean hasDecoupledClock; gint attribute; - gchar *dp_enabled_string; + gint nvclock; + gint memclock; + gint processorclock; GtkWidget *status; GtkWidget *link_width; diff --git a/src/libXNVCtrl/NVCtrl.h b/src/libXNVCtrl/NVCtrl.h index 4933f49..0a7d8de 100644 --- a/src/libXNVCtrl/NVCtrl.h +++ b/src/libXNVCtrl/NVCtrl.h @@ -2679,16 +2679,21 @@ * NV_CTRL_GPU_POWER_MIZER_MODE - Provides a hint to the driver * as to how to manage the performance of the GPU. * - * ADAPTIVE - adjust GPU clocks based on GPU - * utilization - * PREFER_MAXIMUM_PERFORMANCE - raise GPU clocks to favor - * maximum performance, to the extent - * that thermal and other constraints - * allow - */ -#define NV_CTRL_GPU_POWER_MIZER_MODE 334 /* RW-G */ -#define NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE 0 -#define NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_MAXIMUM_PERFORMANCE 1 + * ADAPTIVE - adjust GPU clocks based on GPU + * utilization + * PREFER_MAXIMUM_PERFORMANCE - raise GPU clocks to favor + * maximum performance, to the extent + * that thermal and other constraints + * allow + * AUTO - let the driver choose the performance + * policy + * PREFER_CONSISTENT_PERFORMANCE - lock to GPU base clocks + */ +#define NV_CTRL_GPU_POWER_MIZER_MODE 334 /* RW-G */ +#define NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE 0 +#define NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_MAXIMUM_PERFORMANCE 1 +#define NV_CTRL_GPU_POWER_MIZER_MODE_AUTO 2 +#define NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_CONSISTENT_PERFORMANCE 3 /* * NV_CTRL_GVI_SYNC_OUTPUT_FORMAT - Returns the output sync signal @@ -3267,7 +3272,13 @@ #define NV_CTRL_DPY_HDMI_3D_DISABLED 0 #define NV_CTRL_DPY_HDMI_3D_ENABLED 1 -#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_DPY_HDMI_3D +/* + * NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE - Returns the default PowerMizer mode + * for the given GPU. + */ +#define NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE 400 /* R--G */ + +#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE /**************************************************************************/ @@ -3652,20 +3663,37 @@ * NV_CTRL_STRING_PERFORMANCE_MODES - returns a string with all the * performance modes defined for this GPU along with their associated * NV Clock and Memory Clock values. + * Not all tokens will be reported on all GPUs, and additional tokens + * may be added in the future. + * For backwards compatibility we still provide nvclock, memclock, and + * processorclock those are the same as nvclockmin, memclockmin and + * processorclockmin. * * Each performance modes are returned as a comma-separated list of * "token=value" pairs. Each set of performance mode tokens are separated * by a ";". Valid tokens: * - * Token Value - * "perf" integer - the Performance level - * "nvclock" integer - the GPU clocks (in MHz) for the perf level - * "memclock" integer - the memory clocks (in MHz) for the perf level - * + * Token Value + * "perf" integer - the Performance level + * "nvclock" integer - the GPU clocks (in MHz) for the perf level + * "nvclockmin" integer - the GPU clocks min (in MHz) for the perf level + * "nvclockmax" integer - the GPU clocks max (in MHz) for the perf level + * "memclock" integer - the memory clocks (in MHz) for the perf level + * "memclockmin" integer - the memory clocks min (in MHz) for the perf level + * "memclockmax" integer - the memory clocks max (in MHz) for the perf level + * "processorclock" integer - the processor clocks (in MHz) + * for the perf level + * "processorclockmin" integer - the processor clocks min (in MHz) + * for the perf level + * "processorclockmax" integer - the processor clocks max (in MHz) + * for the perf level * * Example: * - * perf=0, nvclock=500, memclock=505 ; perf=1, nvclock=650, memclock=505 + * perf=0, nvclock=324, nvclockmin=324, nvclockmax=324, memclock=324, + * memclockmin=324, memclockmax=324 ; + * perf=1, nvclock=324, nvclockmin=324, nvclockmax=640, memclock=810, + * memclockmin=810, memclockmax=810 ; * * This attribute may be queried through XNVCTRLQueryTargetStringAttribute() * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. @@ -3777,7 +3805,9 @@ * NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS - returns a string with the * associated NV Clock, Memory Clock and Processor Clock values. * - * Current valid tokens are "nvclock", "memclock", and "processorclock". + * Current valid tokens are "nvclock", "nvclockmin", "nvclockmax", + * "memclock", "memclockmin", "memclockmax", "processorclock", + * "processorclockmin" and "processorclockmax". * Not all tokens will be reported on all GPUs, and additional tokens * may be added in the future. * @@ -3785,17 +3815,24 @@ * "token=value" pairs. * Valid tokens: * - * Token Value - * "nvclock" integer - the GPU clocks (in MHz) for the current - * perf level - * "memclock" integer - the memory clocks (in MHz) for the current - * perf level - * "processorclock" integer - the processor clocks (in MHz) for the perf level - * + * Token Value + * "nvclock" integer - the GPU clocks (in MHz) for the perf level + * "nvclockmin" integer - the GPU clocks min (in MHz) for the perf level + * "nvclockmax" integer - the GPU clocks max (in MHz) for the perf level + * "memclock" integer - the memory clocks (in MHz) for the perf level + * "memclockmin" integer - the memory clocks min (in MHz) for the perf level + * "memclockmax" integer - the memory clocks (max in MHz) for the perf level + * "processorclock" integer - the processor clocks (in MHz) + * for the perf level + * "processorclockmin" integer - the processor clocks min (in MHz) + * for the perf level + * "processorclockmax" integer - the processor clocks max (in MHz) + * for the perf level * * Example: * - * nvclock=459, memclock=400, processorclock=918 + * nvclock=324, nvclockmin=324, nvclockmax=324, + * memclock=324, memclockmin=324, memclockmax=324 * * This attribute may be queried through XNVCTRLQueryTargetStringAttribute() * using an NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. diff --git a/src/parse.c b/src/parse.c index 4e83e97..c547abc 100644 --- a/src/parse.c +++ b/src/parse.c @@ -165,6 +165,7 @@ const AttributeTableEntry attributeTable[] = { { "GPUAdaptiveClockState", NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE, N, "Reports if Adaptive Clocking is Enabled on the GPU driving the X screen." }, { "GPUPerfModes", NV_CTRL_STRING_PERFORMANCE_MODES, S|N, "Returns a string with all the performance modes defined for this GPU along with their associated NV Clock and Memory Clock values." }, { "GPUPowerMizerMode", NV_CTRL_GPU_POWER_MIZER_MODE, 0, "Allows setting different GPU powermizer modes." }, + { "GPUPowerMizerDefaultMode", NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE, N, "Reports the default powermizer mode of the GPU, if any." }, { "ECCSupported", NV_CTRL_GPU_ECC_SUPPORTED, N, "Reports whether the underlying GPU supports ECC. All of the other ECC attributes are only applicable if this attribute indicates that ECC is supported." }, { "ECCStatus", NV_CTRL_GPU_ECC_STATUS, N, "Reports whether ECC is enabled." }, { "ECCConfigurationSupported", NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED, N, "Reports whether ECC whether the ECC configuration setting can be changed." }, @@ -368,7 +369,7 @@ const AttributeTableEntry attributeTable[] = { * about. */ -#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_DPY_HDMI_3D +#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE #warning "Have you forgotten to add a new integer attribute to attributeTable?" #endif diff --git a/src/version.mk b/src/version.mk index 6b57a0b..47298b6 100644 --- a/src/version.mk +++ b/src/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 319.23 +NVIDIA_VERSION = 319.32 diff --git a/version.mk b/version.mk index 6b57a0b..47298b6 100644 --- a/version.mk +++ b/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 319.23 +NVIDIA_VERSION = 319.32 -- cgit v1.2.3