nouveau_pm.c revision 11b7d895216f7f954c6cfa0c23b76dccb7a890c1
1/*
2 * Copyright 2010 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "drmP.h"
26
27#include "nouveau_drv.h"
28#include "nouveau_pm.h"
29
30#ifdef CONFIG_ACPI
31#include <linux/acpi.h>
32#endif
33#include <linux/power_supply.h>
34#include <linux/hwmon.h>
35#include <linux/hwmon-sysfs.h>
36
37static int
38nouveau_pm_clock_set(struct drm_device *dev, struct nouveau_pm_level *perflvl,
39		     u8 id, u32 khz)
40{
41	struct drm_nouveau_private *dev_priv = dev->dev_private;
42	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
43	void *pre_state;
44
45	if (khz == 0)
46		return 0;
47
48	pre_state = pm->clock_pre(dev, perflvl, id, khz);
49	if (IS_ERR(pre_state))
50		return PTR_ERR(pre_state);
51
52	if (pre_state)
53		pm->clock_set(dev, pre_state);
54	return 0;
55}
56
57static int
58nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl)
59{
60	struct drm_nouveau_private *dev_priv = dev->dev_private;
61	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
62	int ret;
63
64	if (perflvl == pm->cur)
65		return 0;
66
67	/*XXX: not on all boards, we should control based on temperature
68	 *     on recent boards..  or maybe on some other factor we don't
69	 *     know about?
70	 */
71	if (pm->fanspeed_set && perflvl->fanspeed) {
72		ret = pm->fanspeed_set(dev, perflvl->fanspeed);
73		if (ret)
74			NV_ERROR(dev, "set fanspeed failed: %d\n", ret);
75	}
76
77	if (pm->voltage.supported && pm->voltage_set && perflvl->volt_min) {
78		ret = pm->voltage_set(dev, perflvl->volt_min);
79		if (ret) {
80			NV_ERROR(dev, "voltage_set %d failed: %d\n",
81				 perflvl->volt_min, ret);
82		}
83	}
84
85	if (pm->clocks_pre) {
86		void *state = pm->clocks_pre(dev, perflvl);
87		if (IS_ERR(state))
88			return PTR_ERR(state);
89		pm->clocks_set(dev, state);
90	} else
91	if (pm->clock_set) {
92		nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core);
93		nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader);
94		nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory);
95		nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05);
96	}
97
98	pm->cur = perflvl;
99	return 0;
100}
101
102static int
103nouveau_pm_profile_set(struct drm_device *dev, const char *profile)
104{
105	struct drm_nouveau_private *dev_priv = dev->dev_private;
106	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
107	struct nouveau_pm_level *perflvl = NULL;
108
109	/* safety precaution, for now */
110	if (nouveau_perflvl_wr != 7777)
111		return -EPERM;
112
113	if (!strncmp(profile, "boot", 4))
114		perflvl = &pm->boot;
115	else {
116		int pl = simple_strtol(profile, NULL, 10);
117		int i;
118
119		for (i = 0; i < pm->nr_perflvl; i++) {
120			if (pm->perflvl[i].id == pl) {
121				perflvl = &pm->perflvl[i];
122				break;
123			}
124		}
125
126		if (!perflvl)
127			return -EINVAL;
128	}
129
130	NV_INFO(dev, "setting performance level: %s\n", profile);
131	return nouveau_pm_perflvl_set(dev, perflvl);
132}
133
134static int
135nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
136{
137	struct drm_nouveau_private *dev_priv = dev->dev_private;
138	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
139	int ret;
140
141	memset(perflvl, 0, sizeof(*perflvl));
142
143	if (pm->clocks_get) {
144		ret = pm->clocks_get(dev, perflvl);
145		if (ret)
146			return ret;
147	} else
148	if (pm->clock_get) {
149		ret = pm->clock_get(dev, PLL_CORE);
150		if (ret > 0)
151			perflvl->core = ret;
152
153		ret = pm->clock_get(dev, PLL_MEMORY);
154		if (ret > 0)
155			perflvl->memory = ret;
156
157		ret = pm->clock_get(dev, PLL_SHADER);
158		if (ret > 0)
159			perflvl->shader = ret;
160
161		ret = pm->clock_get(dev, PLL_UNK05);
162		if (ret > 0)
163			perflvl->unk05 = ret;
164	}
165
166	if (pm->voltage.supported && pm->voltage_get) {
167		ret = pm->voltage_get(dev);
168		if (ret > 0) {
169			perflvl->volt_min = ret;
170			perflvl->volt_max = ret;
171		}
172	}
173
174	if (pm->fanspeed_get) {
175		ret = pm->fanspeed_get(dev);
176		if (ret > 0)
177			perflvl->fanspeed = ret;
178	}
179
180	return 0;
181}
182
183static void
184nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
185{
186	char c[16], s[16], v[32], f[16], t[16], m[16];
187
188	c[0] = '\0';
189	if (perflvl->core)
190		snprintf(c, sizeof(c), " core %dMHz", perflvl->core / 1000);
191
192	s[0] = '\0';
193	if (perflvl->shader)
194		snprintf(s, sizeof(s), " shader %dMHz", perflvl->shader / 1000);
195
196	m[0] = '\0';
197	if (perflvl->memory)
198		snprintf(m, sizeof(m), " memory %dMHz", perflvl->memory / 1000);
199
200	v[0] = '\0';
201	if (perflvl->volt_min && perflvl->volt_min != perflvl->volt_max) {
202		snprintf(v, sizeof(v), " voltage %dmV-%dmV",
203			 perflvl->volt_min / 1000, perflvl->volt_max / 1000);
204	} else
205	if (perflvl->volt_min) {
206		snprintf(v, sizeof(v), " voltage %dmV",
207			 perflvl->volt_min / 1000);
208	}
209
210	f[0] = '\0';
211	if (perflvl->fanspeed)
212		snprintf(f, sizeof(f), " fanspeed %d%%", perflvl->fanspeed);
213
214	t[0] = '\0';
215	if (perflvl->timing)
216		snprintf(t, sizeof(t), " timing %d", perflvl->timing->id);
217
218	snprintf(ptr, len, "%s%s%s%s%s%s\n", c, s, m, t, v, f);
219}
220
221static ssize_t
222nouveau_pm_get_perflvl_info(struct device *d,
223			    struct device_attribute *a, char *buf)
224{
225	struct nouveau_pm_level *perflvl = (struct nouveau_pm_level *)a;
226	char *ptr = buf;
227	int len = PAGE_SIZE;
228
229	snprintf(ptr, len, "%d:", perflvl->id);
230	ptr += strlen(buf);
231	len -= strlen(buf);
232
233	nouveau_pm_perflvl_info(perflvl, ptr, len);
234	return strlen(buf);
235}
236
237static ssize_t
238nouveau_pm_get_perflvl(struct device *d, struct device_attribute *a, char *buf)
239{
240	struct drm_device *dev = pci_get_drvdata(to_pci_dev(d));
241	struct drm_nouveau_private *dev_priv = dev->dev_private;
242	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
243	struct nouveau_pm_level cur;
244	int len = PAGE_SIZE, ret;
245	char *ptr = buf;
246
247	if (!pm->cur)
248		snprintf(ptr, len, "setting: boot\n");
249	else if (pm->cur == &pm->boot)
250		snprintf(ptr, len, "setting: boot\nc:");
251	else
252		snprintf(ptr, len, "setting: static %d\nc:", pm->cur->id);
253	ptr += strlen(buf);
254	len -= strlen(buf);
255
256	ret = nouveau_pm_perflvl_get(dev, &cur);
257	if (ret == 0)
258		nouveau_pm_perflvl_info(&cur, ptr, len);
259	return strlen(buf);
260}
261
262static ssize_t
263nouveau_pm_set_perflvl(struct device *d, struct device_attribute *a,
264		       const char *buf, size_t count)
265{
266	struct drm_device *dev = pci_get_drvdata(to_pci_dev(d));
267	int ret;
268
269	ret = nouveau_pm_profile_set(dev, buf);
270	if (ret)
271		return ret;
272	return strlen(buf);
273}
274
275static DEVICE_ATTR(performance_level, S_IRUGO | S_IWUSR,
276		   nouveau_pm_get_perflvl, nouveau_pm_set_perflvl);
277
278static int
279nouveau_sysfs_init(struct drm_device *dev)
280{
281	struct drm_nouveau_private *dev_priv = dev->dev_private;
282	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
283	struct device *d = &dev->pdev->dev;
284	int ret, i;
285
286	ret = device_create_file(d, &dev_attr_performance_level);
287	if (ret)
288		return ret;
289
290	for (i = 0; i < pm->nr_perflvl; i++) {
291		struct nouveau_pm_level *perflvl = &pm->perflvl[i];
292
293		perflvl->dev_attr.attr.name = perflvl->name;
294		perflvl->dev_attr.attr.mode = S_IRUGO;
295		perflvl->dev_attr.show = nouveau_pm_get_perflvl_info;
296		perflvl->dev_attr.store = NULL;
297		sysfs_attr_init(&perflvl->dev_attr.attr);
298
299		ret = device_create_file(d, &perflvl->dev_attr);
300		if (ret) {
301			NV_ERROR(dev, "failed pervlvl %d sysfs: %d\n",
302				 perflvl->id, i);
303			perflvl->dev_attr.attr.name = NULL;
304			nouveau_pm_fini(dev);
305			return ret;
306		}
307	}
308
309	return 0;
310}
311
312static void
313nouveau_sysfs_fini(struct drm_device *dev)
314{
315	struct drm_nouveau_private *dev_priv = dev->dev_private;
316	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
317	struct device *d = &dev->pdev->dev;
318	int i;
319
320	device_remove_file(d, &dev_attr_performance_level);
321	for (i = 0; i < pm->nr_perflvl; i++) {
322		struct nouveau_pm_level *pl = &pm->perflvl[i];
323
324		if (!pl->dev_attr.attr.name)
325			break;
326
327		device_remove_file(d, &pl->dev_attr);
328	}
329}
330
331#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
332static ssize_t
333nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
334{
335	struct drm_device *dev = dev_get_drvdata(d);
336	struct drm_nouveau_private *dev_priv = dev->dev_private;
337	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
338
339	return snprintf(buf, PAGE_SIZE, "%d\n", pm->temp_get(dev)*1000);
340}
341static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp,
342						  NULL, 0);
343
344static ssize_t
345nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf)
346{
347	struct drm_device *dev = dev_get_drvdata(d);
348	struct drm_nouveau_private *dev_priv = dev->dev_private;
349	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
350	struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp;
351
352	return snprintf(buf, PAGE_SIZE, "%d\n", temp->down_clock*1000);
353}
354static ssize_t
355nouveau_hwmon_set_max_temp(struct device *d, struct device_attribute *a,
356						const char *buf, size_t count)
357{
358	struct drm_device *dev = dev_get_drvdata(d);
359	struct drm_nouveau_private *dev_priv = dev->dev_private;
360	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
361	struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp;
362	long value;
363
364	if (strict_strtol(buf, 10, &value) == -EINVAL)
365		return count;
366
367	temp->down_clock = value/1000;
368
369	nouveau_temp_safety_checks(dev);
370
371	return count;
372}
373static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, nouveau_hwmon_max_temp,
374						  nouveau_hwmon_set_max_temp,
375						  0);
376
377static ssize_t
378nouveau_hwmon_critical_temp(struct device *d, struct device_attribute *a,
379							char *buf)
380{
381	struct drm_device *dev = dev_get_drvdata(d);
382	struct drm_nouveau_private *dev_priv = dev->dev_private;
383	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
384	struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp;
385
386	return snprintf(buf, PAGE_SIZE, "%d\n", temp->critical*1000);
387}
388static ssize_t
389nouveau_hwmon_set_critical_temp(struct device *d, struct device_attribute *a,
390							    const char *buf,
391								size_t count)
392{
393	struct drm_device *dev = dev_get_drvdata(d);
394	struct drm_nouveau_private *dev_priv = dev->dev_private;
395	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
396	struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp;
397	long value;
398
399	if (strict_strtol(buf, 10, &value) == -EINVAL)
400		return count;
401
402	temp->critical = value/1000;
403
404	nouveau_temp_safety_checks(dev);
405
406	return count;
407}
408static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR,
409						nouveau_hwmon_critical_temp,
410						nouveau_hwmon_set_critical_temp,
411						0);
412
413static ssize_t nouveau_hwmon_show_name(struct device *dev,
414				      struct device_attribute *attr,
415				      char *buf)
416{
417	return sprintf(buf, "nouveau\n");
418}
419static SENSOR_DEVICE_ATTR(name, S_IRUGO, nouveau_hwmon_show_name, NULL, 0);
420
421static ssize_t nouveau_hwmon_show_update_rate(struct device *dev,
422				      struct device_attribute *attr,
423				      char *buf)
424{
425	return sprintf(buf, "1000\n");
426}
427static SENSOR_DEVICE_ATTR(update_rate, S_IRUGO,
428						nouveau_hwmon_show_update_rate,
429						NULL, 0);
430
431static ssize_t
432nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr,
433			      char *buf)
434{
435	struct drm_device *dev = dev_get_drvdata(d);
436	struct drm_nouveau_private *dev_priv = dev->dev_private;
437	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
438	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
439	struct dcb_gpio_entry *gpio;
440	u32 cycles, cur, prev;
441	u64 start;
442
443	gpio = nouveau_bios_gpio_entry(dev, DCB_GPIO_FAN_SENSE);
444	if (!gpio)
445		return -ENODEV;
446
447	/* Monitor the GPIO input 0x3b for 250ms.
448	 * When the fan spins, it changes the value of GPIO FAN_SENSE.
449	 * We get 4 changes (0 -> 1 -> 0 -> 1 -> [...]) per complete rotation.
450	 */
451	start = ptimer->read(dev);
452	prev = pgpio->get(dev, DCB_GPIO_FAN_SENSE);
453	cycles = 0;
454	do {
455		cur = pgpio->get(dev, DCB_GPIO_FAN_SENSE);
456		if (prev != cur) {
457			cycles++;
458			prev = cur;
459		}
460
461		usleep_range(500, 1000); /* supports 0 < rpm < 7500 */
462	} while (ptimer->read(dev) - start < 250000000);
463
464	/* interpolate to get rpm */
465	return sprintf(buf, "%i\n", cycles / 4 * 4 * 60);
466}
467static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input,
468			  NULL, 0);
469
470static ssize_t
471nouveau_hwmon_get_pwm0(struct device *d, struct device_attribute *a, char *buf)
472{
473	struct drm_device *dev = dev_get_drvdata(d);
474	struct drm_nouveau_private *dev_priv = dev->dev_private;
475	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
476	int ret = -ENODEV;
477
478	if (pm->fanspeed_get)
479		ret = pm->fanspeed_get(dev);
480	if (ret < 0)
481		return ret;
482
483	return sprintf(buf, "%i\n", ret);
484}
485
486static ssize_t
487nouveau_hwmon_set_pwm0(struct device *d, struct device_attribute *a,
488		       const char *buf, size_t count)
489{
490	struct drm_device *dev = dev_get_drvdata(d);
491	struct drm_nouveau_private *dev_priv = dev->dev_private;
492	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
493	int ret = -ENODEV;
494	long value;
495
496	if (nouveau_perflvl_wr != 7777)
497		return -EPERM;
498
499	if (strict_strtol(buf, 10, &value) == -EINVAL)
500		return -EINVAL;
501
502	if (value < pm->fan.min_duty)
503		value = pm->fan.min_duty;
504	if (value > pm->fan.max_duty)
505		value = pm->fan.max_duty;
506
507	if (pm->fanspeed_set)
508		ret = pm->fanspeed_set(dev, value);
509	if (ret)
510		return ret;
511
512	return count;
513}
514
515static SENSOR_DEVICE_ATTR(pwm0, S_IRUGO | S_IWUSR,
516			  nouveau_hwmon_get_pwm0,
517			  nouveau_hwmon_set_pwm0, 0);
518
519static ssize_t
520nouveau_hwmon_get_pwm0_min(struct device *d,
521			   struct device_attribute *a, char *buf)
522{
523	struct drm_device *dev = dev_get_drvdata(d);
524	struct drm_nouveau_private *dev_priv = dev->dev_private;
525	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
526
527	return sprintf(buf, "%i\n", pm->fan.min_duty);
528}
529
530static ssize_t
531nouveau_hwmon_set_pwm0_min(struct device *d, struct device_attribute *a,
532			   const char *buf, size_t count)
533{
534	struct drm_device *dev = dev_get_drvdata(d);
535	struct drm_nouveau_private *dev_priv = dev->dev_private;
536	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
537	long value;
538
539	if (strict_strtol(buf, 10, &value) == -EINVAL)
540		return -EINVAL;
541
542	if (value < 0)
543		value = 0;
544
545	if (pm->fan.max_duty - value < 10)
546		value = pm->fan.max_duty - 10;
547
548	if (value < 10)
549		pm->fan.min_duty = 10;
550	else
551		pm->fan.min_duty = value;
552
553	return count;
554}
555
556static SENSOR_DEVICE_ATTR(pwm0_min, S_IRUGO | S_IWUSR,
557			  nouveau_hwmon_get_pwm0_min,
558			  nouveau_hwmon_set_pwm0_min, 0);
559
560static ssize_t
561nouveau_hwmon_get_pwm0_max(struct device *d,
562			   struct device_attribute *a, char *buf)
563{
564	struct drm_device *dev = dev_get_drvdata(d);
565	struct drm_nouveau_private *dev_priv = dev->dev_private;
566	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
567
568	return sprintf(buf, "%i\n", pm->fan.max_duty);
569}
570
571static ssize_t
572nouveau_hwmon_set_pwm0_max(struct device *d, struct device_attribute *a,
573			   const char *buf, size_t count)
574{
575	struct drm_device *dev = dev_get_drvdata(d);
576	struct drm_nouveau_private *dev_priv = dev->dev_private;
577	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
578	long value;
579
580	if (strict_strtol(buf, 10, &value) == -EINVAL)
581		return -EINVAL;
582
583	if (value < 0)
584		value = 0;
585
586	if (value - pm->fan.min_duty < 10)
587		value = pm->fan.min_duty + 10;
588
589	if (value > 100)
590		pm->fan.max_duty = 100;
591	else
592		pm->fan.max_duty = value;
593
594	return count;
595}
596
597static SENSOR_DEVICE_ATTR(pwm0_max, S_IRUGO | S_IWUSR,
598			  nouveau_hwmon_get_pwm0_max,
599			  nouveau_hwmon_set_pwm0_max, 0);
600
601static struct attribute *hwmon_attributes[] = {
602	&sensor_dev_attr_temp1_input.dev_attr.attr,
603	&sensor_dev_attr_temp1_max.dev_attr.attr,
604	&sensor_dev_attr_temp1_crit.dev_attr.attr,
605	&sensor_dev_attr_name.dev_attr.attr,
606	&sensor_dev_attr_update_rate.dev_attr.attr,
607	NULL
608};
609static struct attribute *hwmon_fan_rpm_attributes[] = {
610	&sensor_dev_attr_fan0_input.dev_attr.attr,
611	NULL
612};
613static struct attribute *hwmon_pwm_fan_attributes[] = {
614	&sensor_dev_attr_pwm0.dev_attr.attr,
615	&sensor_dev_attr_pwm0_min.dev_attr.attr,
616	&sensor_dev_attr_pwm0_max.dev_attr.attr,
617	NULL
618};
619
620static const struct attribute_group hwmon_attrgroup = {
621	.attrs = hwmon_attributes,
622};
623static const struct attribute_group hwmon_fan_rpm_attrgroup = {
624	.attrs = hwmon_fan_rpm_attributes,
625};
626static const struct attribute_group hwmon_pwm_fan_attrgroup = {
627	.attrs = hwmon_pwm_fan_attributes,
628};
629#endif
630
631static int
632nouveau_hwmon_init(struct drm_device *dev)
633{
634#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
635	struct drm_nouveau_private *dev_priv = dev->dev_private;
636	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
637	struct device *hwmon_dev;
638	int ret = 0;
639
640	if (!pm->temp_get)
641		return -ENODEV;
642
643	hwmon_dev = hwmon_device_register(&dev->pdev->dev);
644	if (IS_ERR(hwmon_dev)) {
645		ret = PTR_ERR(hwmon_dev);
646		NV_ERROR(dev,
647			"Unable to register hwmon device: %d\n", ret);
648		return ret;
649	}
650	dev_set_drvdata(hwmon_dev, dev);
651
652	/* default sysfs entries */
653	ret = sysfs_create_group(&dev->pdev->dev.kobj, &hwmon_attrgroup);
654	if (ret) {
655		if (ret)
656			goto error;
657	}
658
659	/* if the card has a pwm fan */
660	/*XXX: incorrect, need better detection for this, some boards have
661	 *     the gpio entries for pwm fan control even when there's no
662	 *     actual fan connected to it... therm table? */
663	if (pm->fanspeed_get && pm->fanspeed_get(dev) >= 0) {
664		ret = sysfs_create_group(&dev->pdev->dev.kobj,
665					 &hwmon_pwm_fan_attrgroup);
666		if (ret)
667			goto error;
668	}
669
670	/* if the card can read the fan rpm */
671	if (nouveau_bios_gpio_entry(dev, DCB_GPIO_FAN_SENSE)) {
672		ret = sysfs_create_group(&dev->pdev->dev.kobj,
673					 &hwmon_fan_rpm_attrgroup);
674		if (ret)
675			goto error;
676	}
677
678	pm->hwmon = hwmon_dev;
679
680	return 0;
681
682error:
683	NV_ERROR(dev, "Unable to create some hwmon sysfs files: %d\n", ret);
684	hwmon_device_unregister(hwmon_dev);
685	pm->hwmon = NULL;
686	return ret;
687#else
688	pm->hwmon = NULL;
689	return 0;
690#endif
691}
692
693static void
694nouveau_hwmon_fini(struct drm_device *dev)
695{
696#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
697	struct drm_nouveau_private *dev_priv = dev->dev_private;
698	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
699
700	if (pm->hwmon) {
701		sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_attrgroup);
702		sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_pwm_fan_attrgroup);
703		sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_fan_rpm_attrgroup);
704
705		hwmon_device_unregister(pm->hwmon);
706	}
707#endif
708}
709
710#if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY)
711static int
712nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data)
713{
714	struct drm_nouveau_private *dev_priv =
715		container_of(nb, struct drm_nouveau_private, engine.pm.acpi_nb);
716	struct drm_device *dev = dev_priv->dev;
717	struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
718
719	if (strcmp(entry->device_class, "ac_adapter") == 0) {
720		bool ac = power_supply_is_system_supplied();
721
722		NV_DEBUG(dev, "power supply changed: %s\n", ac ? "AC" : "DC");
723	}
724
725	return NOTIFY_OK;
726}
727#endif
728
729int
730nouveau_pm_init(struct drm_device *dev)
731{
732	struct drm_nouveau_private *dev_priv = dev->dev_private;
733	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
734	char info[256];
735	int ret, i;
736
737	nouveau_mem_timing_init(dev);
738	nouveau_volt_init(dev);
739	nouveau_perf_init(dev);
740	nouveau_temp_init(dev);
741
742	NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl);
743	for (i = 0; i < pm->nr_perflvl; i++) {
744		nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info));
745		NV_INFO(dev, "%d:%s", pm->perflvl[i].id, info);
746	}
747
748	/* determine current ("boot") performance level */
749	ret = nouveau_pm_perflvl_get(dev, &pm->boot);
750	if (ret == 0) {
751		strncpy(pm->boot.name, "boot", 4);
752		pm->cur = &pm->boot;
753
754		nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info));
755		NV_INFO(dev, "c:%s", info);
756	}
757
758	/* switch performance levels now if requested */
759	if (nouveau_perflvl != NULL) {
760		ret = nouveau_pm_profile_set(dev, nouveau_perflvl);
761		if (ret) {
762			NV_ERROR(dev, "error setting perflvl \"%s\": %d\n",
763				 nouveau_perflvl, ret);
764		}
765	}
766
767	nouveau_sysfs_init(dev);
768	nouveau_hwmon_init(dev);
769#if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY)
770	pm->acpi_nb.notifier_call = nouveau_pm_acpi_event;
771	register_acpi_notifier(&pm->acpi_nb);
772#endif
773
774	return 0;
775}
776
777void
778nouveau_pm_fini(struct drm_device *dev)
779{
780	struct drm_nouveau_private *dev_priv = dev->dev_private;
781	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
782
783	if (pm->cur != &pm->boot)
784		nouveau_pm_perflvl_set(dev, &pm->boot);
785
786	nouveau_temp_fini(dev);
787	nouveau_perf_fini(dev);
788	nouveau_volt_fini(dev);
789	nouveau_mem_timing_fini(dev);
790
791#if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY)
792	unregister_acpi_notifier(&pm->acpi_nb);
793#endif
794	nouveau_hwmon_fini(dev);
795	nouveau_sysfs_fini(dev);
796}
797
798void
799nouveau_pm_resume(struct drm_device *dev)
800{
801	struct drm_nouveau_private *dev_priv = dev->dev_private;
802	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
803	struct nouveau_pm_level *perflvl;
804
805	if (!pm->cur || pm->cur == &pm->boot)
806		return;
807
808	perflvl = pm->cur;
809	pm->cur = &pm->boot;
810	nouveau_pm_perflvl_set(dev, perflvl);
811}
812