Ejemplo n.º 1
0
static ssize_t
nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
	int temp = nvkm_therm_temp_get(therm);

	if (temp < 0)
		return temp;

	return snprintf(buf, PAGE_SIZE, "%d\n", temp * 1000);
}
Ejemplo n.º 2
0
int
nouveau_hwmon_init(struct drm_device *dev)
{
#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_iccsense *iccsense = nvxx_iccsense(&drm->client.device);
	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
	struct nvkm_volt *volt = nvxx_volt(&drm->client.device);
	const struct attribute_group *special_groups[N_ATTR_GROUPS];
	struct nouveau_hwmon *hwmon;
	struct device *hwmon_dev;
	int ret = 0;
	int i = 0;

	if (!iccsense && !therm && !volt) {
		NV_DEBUG(drm, "Skipping hwmon registration\n");
		return 0;
	}

	hwmon = drm->hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL);
	if (!hwmon)
		return -ENOMEM;
	hwmon->dev = dev;

	if (therm && therm->attr_get && therm->attr_set) {
		if (nvkm_therm_temp_get(therm) >= 0)
			special_groups[i++] = &temp1_auto_point_sensor_group;
		if (therm->fan_get && therm->fan_get(therm) >= 0)
			special_groups[i++] = &pwm_fan_sensor_group;
	}

	special_groups[i] = 0;
	hwmon_dev = hwmon_device_register_with_info(dev->dev, "nouveau", dev,
							&nouveau_chip_info,
							special_groups);
	if (IS_ERR(hwmon_dev)) {
		ret = PTR_ERR(hwmon_dev);
		NV_ERROR(drm, "Unable to register hwmon device: %d\n", ret);
		return ret;
	}

	hwmon->hwmon = hwmon_dev;
	return 0;
#else
	return 0;
#endif
}
Ejemplo n.º 3
0
static int
nouveau_temp_read(struct device *dev, u32 attr, int channel, long *val)
{
	struct drm_device *drm_dev = dev_get_drvdata(dev);
	struct nouveau_drm *drm = nouveau_drm(drm_dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
	int ret;

	if (!therm || !therm->attr_get)
		return -EOPNOTSUPP;

	switch (attr) {
	case hwmon_temp_input:
		ret = nvkm_therm_temp_get(therm);
		*val = ret < 0 ? ret : (ret * 1000);
		break;
	case hwmon_temp_max:
		*val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK)
					* 1000;
		break;
	case hwmon_temp_max_hyst:
		*val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST)
					* 1000;
		break;
	case hwmon_temp_crit:
		*val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL)
					* 1000;
		break;
	case hwmon_temp_crit_hyst:
		*val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL_HYST)
					* 1000;
		break;
	case hwmon_temp_emergency:
		*val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN)
					* 1000;
		break;
	case hwmon_temp_emergency_hyst:
		*val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST)
					* 1000;
		break;
	default:
		return -EOPNOTSUPP;
	}

	return 0;
}
Ejemplo n.º 4
0
static umode_t
nouveau_temp_is_visible(const void *data, u32 attr, int channel)
{
	struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);

	if (!therm || !therm->attr_get || nvkm_therm_temp_get(therm) < 0)
		return 0;

	switch (attr) {
	case hwmon_temp_input:
		return 0444;
	case hwmon_temp_max:
	case hwmon_temp_max_hyst:
	case hwmon_temp_crit:
	case hwmon_temp_crit_hyst:
	case hwmon_temp_emergency:
	case hwmon_temp_emergency_hyst:
		return 0644;
	default:
		return 0;
	}
}
Ejemplo n.º 5
0
int
nouveau_hwmon_init(struct drm_device *dev)
{
#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
	struct nvkm_volt *volt = nvxx_volt(&drm->device);
	struct nvkm_iccsense *iccsense = nvxx_iccsense(&drm->device);
	struct nouveau_hwmon *hwmon;
	struct device *hwmon_dev;
	int ret = 0;

	hwmon = drm->hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL);
	if (!hwmon)
		return -ENOMEM;
	hwmon->dev = dev;

	hwmon_dev = hwmon_device_register(dev->dev);
	if (IS_ERR(hwmon_dev)) {
		ret = PTR_ERR(hwmon_dev);
		NV_ERROR(drm, "Unable to register hwmon device: %d\n", ret);
		return ret;
	}
	dev_set_drvdata(hwmon_dev, dev);

	/* set the default attributes */
	ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup);
	if (ret)
		goto error;

	if (therm && therm->attr_get && therm->attr_set) {
		/* if the card has a working thermal sensor */
		if (nvkm_therm_temp_get(therm) >= 0) {
			ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup);
			if (ret)
				goto error;
		}

		/* if the card has a pwm fan */
		/*XXX: incorrect, need better detection for this, some boards have
		 *     the gpio entries for pwm fan control even when there's no
		 *     actual fan connected to it... therm table? */
		if (therm->fan_get && therm->fan_get(therm) >= 0) {
			ret = sysfs_create_group(&hwmon_dev->kobj,
						 &hwmon_pwm_fan_attrgroup);
			if (ret)
				goto error;
		}
	}

	/* if the card can read the fan rpm */
	if (therm && nvkm_therm_fan_sense(therm) >= 0) {
		ret = sysfs_create_group(&hwmon_dev->kobj,
					 &hwmon_fan_rpm_attrgroup);
		if (ret)
			goto error;
	}

	if (volt && nvkm_volt_get(volt) >= 0) {
		ret = sysfs_create_group(&hwmon_dev->kobj,
					 &hwmon_in0_attrgroup);

		if (ret)
			goto error;
	}

	if (iccsense && iccsense->data_valid && !list_empty(&iccsense->rails)) {
		ret = sysfs_create_group(&hwmon_dev->kobj,
					 &hwmon_power_attrgroup);
		if (ret)
			goto error;
	}

	hwmon->hwmon = hwmon_dev;

	return 0;

error:
	NV_ERROR(drm, "Unable to create some hwmon sysfs files: %d\n", ret);
	hwmon_device_unregister(hwmon_dev);
	hwmon->hwmon = NULL;
	return ret;
#else
	return 0;
#endif
}