Hardware/ATI/ATIGPU.cs
author moel.mich
Sun, 08 May 2011 22:10:13 +0000
changeset 279 6bce967ba1b5
parent 270 ef89cbe45b7c
child 280 2bc456906ad6
permissions -rw-r--r--
Fixed the bus and core clock reading on AMD family 10h model Ah CPUs. The new "Core Performance Boost" feature of these CPUs resulted in very low accuracy of the bus speed (and as a consequence also an inaccurate TSC multiplier). This fixed Issue 205.
moel@1
     1
/*
moel@1
     2
  
moel@1
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@1
     4
moel@1
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@1
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@1
     7
  the License. You may obtain a copy of the License at
moel@1
     8
 
moel@1
     9
  http://www.mozilla.org/MPL/
moel@1
    10
moel@1
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@1
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@1
    13
  for the specific language governing rights and limitations under the License.
moel@1
    14
moel@1
    15
  The Original Code is the Open Hardware Monitor code.
moel@1
    16
moel@1
    17
  The Initial Developer of the Original Code is 
moel@1
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@275
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2011
moel@1
    20
  the Initial Developer. All Rights Reserved.
moel@1
    21
moel@1
    22
  Contributor(s):
moel@1
    23
moel@1
    24
  Alternatively, the contents of this file may be used under the terms of
moel@1
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@1
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@1
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@1
    28
  of those above. If you wish to allow use of your version of this file only
moel@1
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@1
    30
  use your version of this file under the terms of the MPL, indicate your
moel@1
    31
  decision by deleting the provisions above and replace them with the notice
moel@1
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@1
    33
  the provisions above, a recipient may use your version of this file under
moel@1
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@1
    35
 
moel@1
    36
*/
moel@1
    37
moel@1
    38
using System;
moel@166
    39
using System.Globalization;
moel@1
    40
moel@1
    41
namespace OpenHardwareMonitor.Hardware.ATI {
moel@166
    42
  internal sealed class ATIGPU : Hardware {
moel@1
    43
moel@195
    44
    private readonly int adapterIndex;
moel@195
    45
    private readonly int busNumber;
moel@195
    46
    private readonly int deviceNumber;
moel@195
    47
    private readonly Sensor temperature;
moel@195
    48
    private readonly Sensor fan;
moel@195
    49
    private readonly Sensor coreClock;
moel@195
    50
    private readonly Sensor memoryClock;
moel@195
    51
    private readonly Sensor coreVoltage;
moel@195
    52
    private readonly Sensor coreLoad;
moel@247
    53
    private readonly Sensor controlSensor;
moel@247
    54
    private readonly Control fanControl;
moel@247
    55
moel@248
    56
    private bool restoreDefaultFanSpeedRequired = false;
moel@248
    57
    private ADLFanSpeedValue initialFanSpeedValue;    
moel@1
    58
moel@3
    59
    public ATIGPU(string name, int adapterIndex, int busNumber, 
moel@165
    60
      int deviceNumber, ISettings settings) 
moel@275
    61
      : base(name, new Identifier("atigpu", 
moel@275
    62
        adapterIndex.ToString(CultureInfo.InvariantCulture)), settings)
moel@3
    63
    {
moel@1
    64
      this.adapterIndex = adapterIndex;
moel@3
    65
      this.busNumber = busNumber;
moel@3
    66
      this.deviceNumber = deviceNumber;
moel@1
    67
moel@165
    68
      this.temperature = new Sensor("GPU Core", 0, SensorType.Temperature, this, settings);
moel@165
    69
      this.fan = new Sensor("GPU Fan", 0, SensorType.Fan, this, settings);
moel@165
    70
      this.coreClock = new Sensor("GPU Core", 0, SensorType.Clock, this, settings);
moel@165
    71
      this.memoryClock = new Sensor("GPU Memory", 1, SensorType.Clock, this, settings);
moel@165
    72
      this.coreVoltage = new Sensor("GPU Core", 0, SensorType.Voltage, this, settings);
moel@165
    73
      this.coreLoad = new Sensor("GPU Core", 0, SensorType.Load, this, settings);
moel@247
    74
      this.controlSensor = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
moel@247
    75
moel@247
    76
      ADLFanSpeedInfo afsi = new ADLFanSpeedInfo();
moel@247
    77
      if (ADL.ADL_Overdrive5_FanSpeedInfo_Get(adapterIndex, 0, ref afsi)
moel@247
    78
        != ADL.ADL_OK) 
moel@247
    79
      {
moel@247
    80
        afsi.MaxPercent = 100;
moel@247
    81
        afsi.MinPercent = 0;
moel@247
    82
      }
moel@247
    83
moel@247
    84
      this.fanControl = new Control(controlSensor, settings, afsi.MinPercent, 
moel@247
    85
        afsi.MaxPercent);
moel@247
    86
      this.fanControl.ControlModeChanged += ControlModeChanged;
moel@247
    87
      this.fanControl.SoftwareControlValueChanged += 
moel@247
    88
        SoftwareControlValueChanged;
moel@247
    89
      ControlModeChanged(fanControl);
moel@247
    90
      this.controlSensor.Control = fanControl;
moel@1
    91
      Update();                   
moel@1
    92
    }
moel@1
    93
moel@248
    94
    private void SaveDefaultFanSpeed() {
moel@248
    95
      if (!restoreDefaultFanSpeedRequired) {        
moel@248
    96
        initialFanSpeedValue = new ADLFanSpeedValue();
moel@248
    97
        initialFanSpeedValue.SpeedType =
moel@248
    98
          ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
moel@248
    99
        restoreDefaultFanSpeedRequired = 
moel@248
   100
          ADL.ADL_Overdrive5_FanSpeed_Get(adapterIndex, 0,
moel@248
   101
          ref initialFanSpeedValue) == ADL.ADL_OK;
moel@248
   102
      }
moel@248
   103
    }
moel@248
   104
moel@248
   105
    private void RestoreDefaultFanSpeed() {
moel@248
   106
      if (restoreDefaultFanSpeedRequired) {        
moel@248
   107
        ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0,
moel@248
   108
          ref this.initialFanSpeedValue);
moel@248
   109
        restoreDefaultFanSpeedRequired = false;
moel@248
   110
      }
moel@248
   111
    }
moel@248
   112
moel@247
   113
    private void SoftwareControlValueChanged(IControl control) {
moel@247
   114
      if (control.ControlMode == ControlMode.Software) {
moel@248
   115
        SaveDefaultFanSpeed();
moel@247
   116
        ADLFanSpeedValue adlf = new ADLFanSpeedValue();
moel@247
   117
        adlf.SpeedType = ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
moel@247
   118
        adlf.Flags = ADL.ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED;
moel@247
   119
        adlf.FanSpeed = (int)control.SoftwareValue;
moel@247
   120
        ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0, ref adlf);
moel@247
   121
      }
moel@247
   122
    }
moel@247
   123
moel@247
   124
    private void ControlModeChanged(IControl control) {
moel@247
   125
      if (control.ControlMode == ControlMode.Default) {
moel@248
   126
        RestoreDefaultFanSpeed();     
moel@247
   127
      } else {
moel@248
   128
        SoftwareControlValueChanged(control);
moel@247
   129
      }
moel@247
   130
    }
moel@247
   131
moel@3
   132
    public int BusNumber { get { return busNumber; } }
moel@3
   133
moel@3
   134
    public int DeviceNumber { get { return deviceNumber; } }
moel@3
   135
moel@1
   136
moel@165
   137
    public override HardwareType HardwareType {
moel@176
   138
      get { return HardwareType.GpuAti; }
moel@1
   139
    }
moel@1
   140
moel@110
   141
    public override void Update() {
moel@1
   142
      ADLTemperature adlt = new ADLTemperature();
moel@15
   143
      if (ADL.ADL_Overdrive5_Temperature_Get(adapterIndex, 0, ref adlt)
moel@15
   144
        == ADL.ADL_OK) 
moel@15
   145
      {
moel@15
   146
        temperature.Value = 0.001f * adlt.Temperature;
moel@15
   147
        ActivateSensor(temperature);
moel@15
   148
      } else {
moel@164
   149
        temperature.Value = null;
moel@15
   150
      }
moel@1
   151
moel@1
   152
      ADLFanSpeedValue adlf = new ADLFanSpeedValue();
moel@1
   153
      adlf.SpeedType = ADL.ADL_DL_FANCTRL_SPEED_TYPE_RPM;
moel@15
   154
      if (ADL.ADL_Overdrive5_FanSpeed_Get(adapterIndex, 0, ref adlf)
moel@15
   155
        == ADL.ADL_OK) 
moel@15
   156
      {
moel@15
   157
        fan.Value = adlf.FanSpeed;
moel@15
   158
        ActivateSensor(fan);
moel@15
   159
      } else {
moel@164
   160
        fan.Value = null;
moel@164
   161
      }
moel@164
   162
moel@164
   163
      adlf = new ADLFanSpeedValue();
moel@164
   164
      adlf.SpeedType = ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
moel@164
   165
      if (ADL.ADL_Overdrive5_FanSpeed_Get(adapterIndex, 0, ref adlf)
moel@164
   166
        == ADL.ADL_OK) {
moel@247
   167
        controlSensor.Value = adlf.FanSpeed;
moel@247
   168
        ActivateSensor(controlSensor);
moel@164
   169
      } else {
moel@247
   170
        controlSensor.Value = null;
moel@15
   171
      }
moel@1
   172
moel@1
   173
      ADLPMActivity adlp = new ADLPMActivity();
moel@15
   174
      if (ADL.ADL_Overdrive5_CurrentActivity_Get(adapterIndex, ref adlp)
moel@15
   175
        == ADL.ADL_OK) 
moel@15
   176
      {
moel@80
   177
        if (adlp.EngineClock > 0) {
moel@80
   178
          coreClock.Value = 0.01f * adlp.EngineClock;
moel@80
   179
          ActivateSensor(coreClock);
moel@270
   180
        } else {
moel@270
   181
          coreClock.Value = null;
moel@80
   182
        }
moel@80
   183
moel@80
   184
        if (adlp.MemoryClock > 0) {
moel@80
   185
          memoryClock.Value = 0.01f * adlp.MemoryClock;
moel@80
   186
          ActivateSensor(memoryClock);
moel@270
   187
        } else {
moel@270
   188
          memoryClock.Value = null;
moel@80
   189
        }
moel@80
   190
moel@80
   191
        if (adlp.Vddc > 0) {
moel@80
   192
          coreVoltage.Value = 0.001f * adlp.Vddc;
moel@80
   193
          ActivateSensor(coreVoltage);
moel@270
   194
        } else {
moel@270
   195
          coreVoltage.Value = null;
moel@80
   196
        }
moel@80
   197
moel@126
   198
        coreLoad.Value = Math.Min(adlp.ActivityPercent, 100);                        
moel@24
   199
        ActivateSensor(coreLoad);
moel@15
   200
      } else {
moel@164
   201
        coreClock.Value = null;
moel@164
   202
        memoryClock.Value = null;
moel@164
   203
        coreVoltage.Value = null;
moel@164
   204
        coreLoad.Value = null;
moel@15
   205
      }
moel@1
   206
    }
moel@247
   207
moel@247
   208
    public void Close() {
moel@247
   209
      this.fanControl.ControlModeChanged -= ControlModeChanged;
moel@247
   210
      this.fanControl.SoftwareControlValueChanged -=
moel@247
   211
        SoftwareControlValueChanged;
moel@247
   212
moel@248
   213
      RestoreDefaultFanSpeed();
moel@247
   214
    }
moel@1
   215
  }
moel@1
   216
}