static ssize_t nouveau_hwmon_set_max_temp(struct device *d, struct device_attribute *a, const char *buf, size_t count) { struct drm_device *dev = dev_get_drvdata(d); struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pm_engine *pm = &dev_priv->engine.pm; struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; long value; if (strict_strtol(buf, 10, &value) == -EINVAL) return count; temp->down_clock = value/1000; nouveau_temp_safety_checks(dev); return count; }
static void nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pm_engine *pm = &dev_priv->engine.pm; struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp; int i, headerlen, recordlen, entries; if (!temp) { NV_DEBUG(dev, "temperature table pointer invalid\n"); return; } /* Set the default sensor's contants */ sensor->offset_constant = 0; sensor->offset_mult = 1; sensor->offset_div = 1; sensor->slope_mult = 1; sensor->slope_div = 1; /* Set the default temperature thresholds */ temps->critical = 110; temps->down_clock = 100; temps->fan_boost = 90; /* Set the known default values to setup the temperature sensor */ if (dev_priv->card_type >= NV_40) { switch (dev_priv->chipset) { case 0x43: sensor->offset_mult = 32060; sensor->offset_div = 1000; sensor->slope_mult = 792; sensor->slope_div = 1000; break; case 0x44: case 0x47: case 0x4a: sensor->offset_mult = 27839; sensor->offset_div = 1000; sensor->slope_mult = 780; sensor->slope_div = 1000; break; case 0x46: sensor->offset_mult = -24775; sensor->offset_div = 100; sensor->slope_mult = 467; sensor->slope_div = 10000; break; case 0x49: sensor->offset_mult = -25051; sensor->offset_div = 100; sensor->slope_mult = 458; sensor->slope_div = 10000; break; case 0x4b: sensor->offset_mult = -24088; sensor->offset_div = 100; sensor->slope_mult = 442; sensor->slope_div = 10000; break; case 0x50: sensor->offset_mult = -22749; sensor->offset_div = 100; sensor->slope_mult = 431; sensor->slope_div = 10000; break; } } headerlen = temp[1]; recordlen = temp[2]; entries = temp[3]; temp = temp + headerlen; /* Read the entries from the table */ for (i = 0; i < entries; i++) { u16 value = ROM16(temp[1]); switch (temp[0]) { case 0x01: if ((value & 0x8f) == 0) sensor->offset_constant = (value >> 9) & 0x7f; break; case 0x04: if ((value & 0xf00f) == 0xa000) /* core */ temps->critical = (value&0x0ff0) >> 4; break; case 0x07: if ((value & 0xf00f) == 0xa000) /* core */ temps->down_clock = (value&0x0ff0) >> 4; break; case 0x08: if ((value & 0xf00f) == 0xa000) /* core */ temps->fan_boost = (value&0x0ff0) >> 4; break; case 0x10: sensor->offset_mult = value; break; case 0x11: sensor->offset_div = value; break; case 0x12: sensor->slope_mult = value; break; case 0x13: sensor->slope_div = value; break; case 0x22: pm->fan.min_duty = value & 0xff; pm->fan.max_duty = (value & 0xff00) >> 8; break; case 0x26: pm->fan.pwm_freq = value; break; } temp += recordlen; } nouveau_temp_safety_checks(dev); /* check the fan min/max settings */ if (pm->fan.min_duty < 10) pm->fan.min_duty = 10; if (pm->fan.max_duty > 100) pm->fan.max_duty = 100; if (pm->fan.max_duty < pm->fan.min_duty) pm->fan.max_duty = pm->fan.min_duty; }