]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/nouveau/nouveau_pm.c
drm/nouveau: port remainder of drm code, and rip out compat layer
[karo-tx-linux.git] / drivers / gpu / drm / nouveau / nouveau_pm.c
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 #ifdef CONFIG_ACPI
26 #include <linux/acpi.h>
27 #endif
28 #include <linux/power_supply.h>
29 #include <linux/hwmon.h>
30 #include <linux/hwmon-sysfs.h>
31
32 #include "drmP.h"
33
34 #include "nouveau_drm.h"
35 #include "nouveau_pm.h"
36
37 #include <subdev/bios/gpio.h>
38 #include <subdev/gpio.h>
39 #include <subdev/timer.h>
40
41 MODULE_PARM_DESC(perflvl, "Performance level (default: boot)");
42 static char *nouveau_perflvl;
43 module_param_named(perflvl, nouveau_perflvl, charp, 0400);
44
45 MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)");
46 static int nouveau_perflvl_wr;
47 module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400);
48
49 static int
50 nouveau_pwmfan_get(struct drm_device *dev)
51 {
52         struct nouveau_pm *pm = nouveau_pm(dev);
53         struct nouveau_drm *drm = nouveau_drm(dev);
54         struct nouveau_device *device = nv_device(drm->device);
55         struct nouveau_gpio *gpio = nouveau_gpio(device);
56         struct dcb_gpio_func func;
57         u32 divs, duty;
58         int ret;
59
60         if (!pm->pwm_get)
61                 return -ENODEV;
62
63         ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func);
64         if (ret == 0) {
65                 ret = pm->pwm_get(dev, func.line, &divs, &duty);
66                 if (ret == 0 && divs) {
67                         divs = max(divs, duty);
68                         if (device->card_type <= NV_40 || (func.log[0] & 1))
69                                 duty = divs - duty;
70                         return (duty * 100) / divs;
71                 }
72
73                 return gpio->get(gpio, 0, func.func, func.line) * 100;
74         }
75
76         return -ENODEV;
77 }
78
79 static int
80 nouveau_pwmfan_set(struct drm_device *dev, int percent)
81 {
82         struct nouveau_pm *pm = nouveau_pm(dev);
83         struct nouveau_drm *drm = nouveau_drm(dev);
84         struct nouveau_device *device = nv_device(drm->device);
85         struct nouveau_gpio *gpio = nouveau_gpio(device);
86         struct dcb_gpio_func func;
87         u32 divs, duty;
88         int ret;
89
90         if (!pm->pwm_set)
91                 return -ENODEV;
92
93         ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func);
94         if (ret == 0) {
95                 divs = pm->fan.pwm_divisor;
96                 if (pm->fan.pwm_freq) {
97                         /*XXX: PNVIO clock more than likely... */
98                         divs = 135000 / pm->fan.pwm_freq;
99                         if (nv_device(drm->device)->chipset < 0xa3)
100                                 divs /= 4;
101                 }
102
103                 duty = ((divs * percent) + 99) / 100;
104                 if (device->card_type <= NV_40 || (func.log[0] & 1))
105                         duty = divs - duty;
106
107                 ret = pm->pwm_set(dev, func.line, divs, duty);
108                 if (!ret)
109                         pm->fan.percent = percent;
110                 return ret;
111         }
112
113         return -ENODEV;
114 }
115
116 static int
117 nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl,
118                        struct nouveau_pm_level *a, struct nouveau_pm_level *b)
119 {
120         struct nouveau_drm *drm = nouveau_drm(dev);
121         struct nouveau_pm *pm = nouveau_pm(dev);
122         int ret;
123
124         /*XXX: not on all boards, we should control based on temperature
125          *     on recent boards..  or maybe on some other factor we don't
126          *     know about?
127          */
128         if (a->fanspeed && b->fanspeed && b->fanspeed > a->fanspeed) {
129                 ret = nouveau_pwmfan_set(dev, perflvl->fanspeed);
130                 if (ret && ret != -ENODEV) {
131                         NV_ERROR(drm, "fanspeed set failed: %d\n", ret);
132                         return ret;
133                 }
134         }
135
136         if (pm->voltage.supported && pm->voltage_set) {
137                 if (perflvl->volt_min && b->volt_min > a->volt_min) {
138                         ret = pm->voltage_set(dev, perflvl->volt_min);
139                         if (ret) {
140                                 NV_ERROR(drm, "voltage set failed: %d\n", ret);
141                                 return ret;
142                         }
143                 }
144         }
145
146         return 0;
147 }
148
149 static int
150 nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl)
151 {
152         struct nouveau_pm *pm = nouveau_pm(dev);
153         void *state;
154         int ret;
155
156         if (perflvl == pm->cur)
157                 return 0;
158
159         ret = nouveau_pm_perflvl_aux(dev, perflvl, pm->cur, perflvl);
160         if (ret)
161                 return ret;
162
163         state = pm->clocks_pre(dev, perflvl);
164         if (IS_ERR(state)) {
165                 ret = PTR_ERR(state);
166                 goto error;
167         }
168         ret = pm->clocks_set(dev, state);
169         if (ret)
170                 goto error;
171
172         ret = nouveau_pm_perflvl_aux(dev, perflvl, perflvl, pm->cur);
173         if (ret)
174                 return ret;
175
176         pm->cur = perflvl;
177         return 0;
178
179 error:
180         /* restore the fan speed and voltage before leaving */
181         nouveau_pm_perflvl_aux(dev, perflvl, perflvl, pm->cur);
182         return ret;
183 }
184
185 void
186 nouveau_pm_trigger(struct drm_device *dev)
187 {
188         struct nouveau_drm *drm = nouveau_drm(dev);
189         struct nouveau_timer *ptimer = nouveau_timer(drm->device);
190         struct nouveau_pm *pm = nouveau_pm(dev);
191         struct nouveau_pm_profile *profile = NULL;
192         struct nouveau_pm_level *perflvl = NULL;
193         int ret;
194
195         /* select power profile based on current power source */
196         if (power_supply_is_system_supplied())
197                 profile = pm->profile_ac;
198         else
199                 profile = pm->profile_dc;
200
201         if (profile != pm->profile) {
202                 pm->profile->func->fini(pm->profile);
203                 pm->profile = profile;
204                 pm->profile->func->init(pm->profile);
205         }
206
207         /* select performance level based on profile */
208         perflvl = profile->func->select(profile);
209
210         /* change perflvl, if necessary */
211         if (perflvl != pm->cur) {
212                 u64 time0 = ptimer->read(ptimer);
213
214                 NV_INFO(drm, "setting performance level: %d", perflvl->id);
215                 ret = nouveau_pm_perflvl_set(dev, perflvl);
216                 if (ret)
217                         NV_INFO(drm, "> reclocking failed: %d\n\n", ret);
218
219                 NV_INFO(drm, "> reclocking took %lluns\n\n",
220                              ptimer->read(ptimer) - time0);
221         }
222 }
223
224 static struct nouveau_pm_profile *
225 profile_find(struct drm_device *dev, const char *string)
226 {
227         struct nouveau_pm *pm = nouveau_pm(dev);
228         struct nouveau_pm_profile *profile;
229
230         list_for_each_entry(profile, &pm->profiles, head) {
231                 if (!strncmp(profile->name, string, sizeof(profile->name)))
232                         return profile;
233         }
234
235         return NULL;
236 }
237
238 static int
239 nouveau_pm_profile_set(struct drm_device *dev, const char *profile)
240 {
241         struct nouveau_pm *pm = nouveau_pm(dev);
242         struct nouveau_pm_profile *ac = NULL, *dc = NULL;
243         char string[16], *cur = string, *ptr;
244
245         /* safety precaution, for now */
246         if (nouveau_perflvl_wr != 7777)
247                 return -EPERM;
248
249         strncpy(string, profile, sizeof(string));
250         string[sizeof(string) - 1] = 0;
251         if ((ptr = strchr(string, '\n')))
252                 *ptr = '\0';
253
254         ptr = strsep(&cur, ",");
255         if (ptr)
256                 ac = profile_find(dev, ptr);
257
258         ptr = strsep(&cur, ",");
259         if (ptr)
260                 dc = profile_find(dev, ptr);
261         else
262                 dc = ac;
263
264         if (ac == NULL || dc == NULL)
265                 return -EINVAL;
266
267         pm->profile_ac = ac;
268         pm->profile_dc = dc;
269         nouveau_pm_trigger(dev);
270         return 0;
271 }
272
273 static void
274 nouveau_pm_static_dummy(struct nouveau_pm_profile *profile)
275 {
276 }
277
278 static struct nouveau_pm_level *
279 nouveau_pm_static_select(struct nouveau_pm_profile *profile)
280 {
281         return container_of(profile, struct nouveau_pm_level, profile);
282 }
283
284 const struct nouveau_pm_profile_func nouveau_pm_static_profile_func = {
285         .destroy = nouveau_pm_static_dummy,
286         .init = nouveau_pm_static_dummy,
287         .fini = nouveau_pm_static_dummy,
288         .select = nouveau_pm_static_select,
289 };
290
291 static int
292 nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
293 {
294         struct nouveau_pm *pm = nouveau_pm(dev);
295         int ret;
296
297         memset(perflvl, 0, sizeof(*perflvl));
298
299         if (pm->clocks_get) {
300                 ret = pm->clocks_get(dev, perflvl);
301                 if (ret)
302                         return ret;
303         }
304
305         if (pm->voltage.supported && pm->voltage_get) {
306                 ret = pm->voltage_get(dev);
307                 if (ret > 0) {
308                         perflvl->volt_min = ret;
309                         perflvl->volt_max = ret;
310                 }
311         }
312
313         ret = nouveau_pwmfan_get(dev);
314         if (ret > 0)
315                 perflvl->fanspeed = ret;
316
317         nouveau_mem_timing_read(dev, &perflvl->timing);
318         return 0;
319 }
320
321 static void
322 nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
323 {
324         char c[16], s[16], v[32], f[16], m[16];
325
326         c[0] = '\0';
327         if (perflvl->core)
328                 snprintf(c, sizeof(c), " core %dMHz", perflvl->core / 1000);
329
330         s[0] = '\0';
331         if (perflvl->shader)
332                 snprintf(s, sizeof(s), " shader %dMHz", perflvl->shader / 1000);
333
334         m[0] = '\0';
335         if (perflvl->memory)
336                 snprintf(m, sizeof(m), " memory %dMHz", perflvl->memory / 1000);
337
338         v[0] = '\0';
339         if (perflvl->volt_min && perflvl->volt_min != perflvl->volt_max) {
340                 snprintf(v, sizeof(v), " voltage %dmV-%dmV",
341                          perflvl->volt_min / 1000, perflvl->volt_max / 1000);
342         } else
343         if (perflvl->volt_min) {
344                 snprintf(v, sizeof(v), " voltage %dmV",
345                          perflvl->volt_min / 1000);
346         }
347
348         f[0] = '\0';
349         if (perflvl->fanspeed)
350                 snprintf(f, sizeof(f), " fanspeed %d%%", perflvl->fanspeed);
351
352         snprintf(ptr, len, "%s%s%s%s%s\n", c, s, m, v, f);
353 }
354
355 static ssize_t
356 nouveau_pm_get_perflvl_info(struct device *d,
357                             struct device_attribute *a, char *buf)
358 {
359         struct nouveau_pm_level *perflvl =
360                 container_of(a, struct nouveau_pm_level, dev_attr);
361         char *ptr = buf;
362         int len = PAGE_SIZE;
363
364         snprintf(ptr, len, "%d:", perflvl->id);
365         ptr += strlen(buf);
366         len -= strlen(buf);
367
368         nouveau_pm_perflvl_info(perflvl, ptr, len);
369         return strlen(buf);
370 }
371
372 static ssize_t
373 nouveau_pm_get_perflvl(struct device *d, struct device_attribute *a, char *buf)
374 {
375         struct drm_device *dev = pci_get_drvdata(to_pci_dev(d));
376         struct nouveau_pm *pm = nouveau_pm(dev);
377         struct nouveau_pm_level cur;
378         int len = PAGE_SIZE, ret;
379         char *ptr = buf;
380
381         snprintf(ptr, len, "profile: %s, %s\nc:",
382                  pm->profile_ac->name, pm->profile_dc->name);
383         ptr += strlen(buf);
384         len -= strlen(buf);
385
386         ret = nouveau_pm_perflvl_get(dev, &cur);
387         if (ret == 0)
388                 nouveau_pm_perflvl_info(&cur, ptr, len);
389         return strlen(buf);
390 }
391
392 static ssize_t
393 nouveau_pm_set_perflvl(struct device *d, struct device_attribute *a,
394                        const char *buf, size_t count)
395 {
396         struct drm_device *dev = pci_get_drvdata(to_pci_dev(d));
397         int ret;
398
399         ret = nouveau_pm_profile_set(dev, buf);
400         if (ret)
401                 return ret;
402         return strlen(buf);
403 }
404
405 static DEVICE_ATTR(performance_level, S_IRUGO | S_IWUSR,
406                    nouveau_pm_get_perflvl, nouveau_pm_set_perflvl);
407
408 static int
409 nouveau_sysfs_init(struct drm_device *dev)
410 {
411         struct nouveau_drm *drm = nouveau_drm(dev);
412         struct nouveau_pm *pm = nouveau_pm(dev);
413         struct device *d = &dev->pdev->dev;
414         int ret, i;
415
416         ret = device_create_file(d, &dev_attr_performance_level);
417         if (ret)
418                 return ret;
419
420         for (i = 0; i < pm->nr_perflvl; i++) {
421                 struct nouveau_pm_level *perflvl = &pm->perflvl[i];
422
423                 perflvl->dev_attr.attr.name = perflvl->name;
424                 perflvl->dev_attr.attr.mode = S_IRUGO;
425                 perflvl->dev_attr.show = nouveau_pm_get_perflvl_info;
426                 perflvl->dev_attr.store = NULL;
427                 sysfs_attr_init(&perflvl->dev_attr.attr);
428
429                 ret = device_create_file(d, &perflvl->dev_attr);
430                 if (ret) {
431                         NV_ERROR(drm, "failed pervlvl %d sysfs: %d\n",
432                                  perflvl->id, i);
433                         perflvl->dev_attr.attr.name = NULL;
434                         nouveau_pm_fini(dev);
435                         return ret;
436                 }
437         }
438
439         return 0;
440 }
441
442 static void
443 nouveau_sysfs_fini(struct drm_device *dev)
444 {
445         struct nouveau_pm *pm = nouveau_pm(dev);
446         struct device *d = &dev->pdev->dev;
447         int i;
448
449         device_remove_file(d, &dev_attr_performance_level);
450         for (i = 0; i < pm->nr_perflvl; i++) {
451                 struct nouveau_pm_level *pl = &pm->perflvl[i];
452
453                 if (!pl->dev_attr.attr.name)
454                         break;
455
456                 device_remove_file(d, &pl->dev_attr);
457         }
458 }
459
460 #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
461 static ssize_t
462 nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
463 {
464         struct drm_device *dev = dev_get_drvdata(d);
465         struct nouveau_pm *pm = nouveau_pm(dev);
466
467         return snprintf(buf, PAGE_SIZE, "%d\n", pm->temp_get(dev)*1000);
468 }
469 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp,
470                                                   NULL, 0);
471
472 static ssize_t
473 nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf)
474 {
475         struct drm_device *dev = dev_get_drvdata(d);
476         struct nouveau_pm *pm = nouveau_pm(dev);
477         struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp;
478
479         return snprintf(buf, PAGE_SIZE, "%d\n", temp->down_clock*1000);
480 }
481 static ssize_t
482 nouveau_hwmon_set_max_temp(struct device *d, struct device_attribute *a,
483                                                 const char *buf, size_t count)
484 {
485         struct drm_device *dev = dev_get_drvdata(d);
486         struct nouveau_pm *pm = nouveau_pm(dev);
487         struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp;
488         long value;
489
490         if (kstrtol(buf, 10, &value) == -EINVAL)
491                 return count;
492
493         temp->down_clock = value/1000;
494
495         nouveau_temp_safety_checks(dev);
496
497         return count;
498 }
499 static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, nouveau_hwmon_max_temp,
500                                                   nouveau_hwmon_set_max_temp,
501                                                   0);
502
503 static ssize_t
504 nouveau_hwmon_critical_temp(struct device *d, struct device_attribute *a,
505                                                         char *buf)
506 {
507         struct drm_device *dev = dev_get_drvdata(d);
508         struct nouveau_pm *pm = nouveau_pm(dev);
509         struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp;
510
511         return snprintf(buf, PAGE_SIZE, "%d\n", temp->critical*1000);
512 }
513 static ssize_t
514 nouveau_hwmon_set_critical_temp(struct device *d, struct device_attribute *a,
515                                                             const char *buf,
516                                                                 size_t count)
517 {
518         struct drm_device *dev = dev_get_drvdata(d);
519         struct nouveau_pm *pm = nouveau_pm(dev);
520         struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp;
521         long value;
522
523         if (kstrtol(buf, 10, &value) == -EINVAL)
524                 return count;
525
526         temp->critical = value/1000;
527
528         nouveau_temp_safety_checks(dev);
529
530         return count;
531 }
532 static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR,
533                                                 nouveau_hwmon_critical_temp,
534                                                 nouveau_hwmon_set_critical_temp,
535                                                 0);
536
537 static ssize_t nouveau_hwmon_show_name(struct device *dev,
538                                       struct device_attribute *attr,
539                                       char *buf)
540 {
541         return sprintf(buf, "nouveau\n");
542 }
543 static SENSOR_DEVICE_ATTR(name, S_IRUGO, nouveau_hwmon_show_name, NULL, 0);
544
545 static ssize_t nouveau_hwmon_show_update_rate(struct device *dev,
546                                       struct device_attribute *attr,
547                                       char *buf)
548 {
549         return sprintf(buf, "1000\n");
550 }
551 static SENSOR_DEVICE_ATTR(update_rate, S_IRUGO,
552                                                 nouveau_hwmon_show_update_rate,
553                                                 NULL, 0);
554
555 static ssize_t
556 nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr,
557                               char *buf)
558 {
559         struct drm_device *dev = dev_get_drvdata(d);
560         struct nouveau_drm *drm = nouveau_drm(dev);
561         struct nouveau_timer *ptimer = nouveau_timer(drm->device);
562         struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
563         struct dcb_gpio_func func;
564         u32 cycles, cur, prev;
565         u64 start;
566
567         if (gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func))
568                 return -ENODEV;
569
570         /* Monitor the GPIO input 0x3b for 250ms.
571          * When the fan spins, it changes the value of GPIO FAN_SENSE.
572          * We get 4 changes (0 -> 1 -> 0 -> 1 -> [...]) per complete rotation.
573          */
574         start = ptimer->read(ptimer);
575         prev = gpio->get(gpio, 0, func.func, func.line);
576         cycles = 0;
577         do {
578                 cur = gpio->get(gpio, 0, func.func, func.line);
579                 if (prev != cur) {
580                         cycles++;
581                         prev = cur;
582                 }
583
584                 usleep_range(500, 1000); /* supports 0 < rpm < 7500 */
585         } while (ptimer->read(ptimer) - start < 250000000);
586
587         /* interpolate to get rpm */
588         return sprintf(buf, "%i\n", cycles / 4 * 4 * 60);
589 }
590 static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input,
591                           NULL, 0);
592
593 static ssize_t
594 nouveau_hwmon_get_pwm0(struct device *d, struct device_attribute *a, char *buf)
595 {
596         struct drm_device *dev = dev_get_drvdata(d);
597         int ret;
598
599         ret = nouveau_pwmfan_get(dev);
600         if (ret < 0)
601                 return ret;
602
603         return sprintf(buf, "%i\n", ret);
604 }
605
606 static ssize_t
607 nouveau_hwmon_set_pwm0(struct device *d, struct device_attribute *a,
608                        const char *buf, size_t count)
609 {
610         struct drm_device *dev = dev_get_drvdata(d);
611         struct nouveau_pm *pm = nouveau_pm(dev);
612         int ret = -ENODEV;
613         long value;
614
615         if (nouveau_perflvl_wr != 7777)
616                 return -EPERM;
617
618         if (kstrtol(buf, 10, &value) == -EINVAL)
619                 return -EINVAL;
620
621         if (value < pm->fan.min_duty)
622                 value = pm->fan.min_duty;
623         if (value > pm->fan.max_duty)
624                 value = pm->fan.max_duty;
625
626         ret = nouveau_pwmfan_set(dev, value);
627         if (ret)
628                 return ret;
629
630         return count;
631 }
632
633 static SENSOR_DEVICE_ATTR(pwm0, S_IRUGO | S_IWUSR,
634                           nouveau_hwmon_get_pwm0,
635                           nouveau_hwmon_set_pwm0, 0);
636
637 static ssize_t
638 nouveau_hwmon_get_pwm0_min(struct device *d,
639                            struct device_attribute *a, char *buf)
640 {
641         struct drm_device *dev = dev_get_drvdata(d);
642         struct nouveau_pm *pm = nouveau_pm(dev);
643
644         return sprintf(buf, "%i\n", pm->fan.min_duty);
645 }
646
647 static ssize_t
648 nouveau_hwmon_set_pwm0_min(struct device *d, struct device_attribute *a,
649                            const char *buf, size_t count)
650 {
651         struct drm_device *dev = dev_get_drvdata(d);
652         struct nouveau_pm *pm = nouveau_pm(dev);
653         long value;
654
655         if (kstrtol(buf, 10, &value) == -EINVAL)
656                 return -EINVAL;
657
658         if (value < 0)
659                 value = 0;
660
661         if (pm->fan.max_duty - value < 10)
662                 value = pm->fan.max_duty - 10;
663
664         if (value < 10)
665                 pm->fan.min_duty = 10;
666         else
667                 pm->fan.min_duty = value;
668
669         return count;
670 }
671
672 static SENSOR_DEVICE_ATTR(pwm0_min, S_IRUGO | S_IWUSR,
673                           nouveau_hwmon_get_pwm0_min,
674                           nouveau_hwmon_set_pwm0_min, 0);
675
676 static ssize_t
677 nouveau_hwmon_get_pwm0_max(struct device *d,
678                            struct device_attribute *a, char *buf)
679 {
680         struct drm_device *dev = dev_get_drvdata(d);
681         struct nouveau_pm *pm = nouveau_pm(dev);
682
683         return sprintf(buf, "%i\n", pm->fan.max_duty);
684 }
685
686 static ssize_t
687 nouveau_hwmon_set_pwm0_max(struct device *d, struct device_attribute *a,
688                            const char *buf, size_t count)
689 {
690         struct drm_device *dev = dev_get_drvdata(d);
691         struct nouveau_pm *pm = nouveau_pm(dev);
692         long value;
693
694         if (kstrtol(buf, 10, &value) == -EINVAL)
695                 return -EINVAL;
696
697         if (value < 0)
698                 value = 0;
699
700         if (value - pm->fan.min_duty < 10)
701                 value = pm->fan.min_duty + 10;
702
703         if (value > 100)
704                 pm->fan.max_duty = 100;
705         else
706                 pm->fan.max_duty = value;
707
708         return count;
709 }
710
711 static SENSOR_DEVICE_ATTR(pwm0_max, S_IRUGO | S_IWUSR,
712                           nouveau_hwmon_get_pwm0_max,
713                           nouveau_hwmon_set_pwm0_max, 0);
714
715 static struct attribute *hwmon_attributes[] = {
716         &sensor_dev_attr_temp1_input.dev_attr.attr,
717         &sensor_dev_attr_temp1_max.dev_attr.attr,
718         &sensor_dev_attr_temp1_crit.dev_attr.attr,
719         &sensor_dev_attr_name.dev_attr.attr,
720         &sensor_dev_attr_update_rate.dev_attr.attr,
721         NULL
722 };
723 static struct attribute *hwmon_fan_rpm_attributes[] = {
724         &sensor_dev_attr_fan0_input.dev_attr.attr,
725         NULL
726 };
727 static struct attribute *hwmon_pwm_fan_attributes[] = {
728         &sensor_dev_attr_pwm0.dev_attr.attr,
729         &sensor_dev_attr_pwm0_min.dev_attr.attr,
730         &sensor_dev_attr_pwm0_max.dev_attr.attr,
731         NULL
732 };
733
734 static const struct attribute_group hwmon_attrgroup = {
735         .attrs = hwmon_attributes,
736 };
737 static const struct attribute_group hwmon_fan_rpm_attrgroup = {
738         .attrs = hwmon_fan_rpm_attributes,
739 };
740 static const struct attribute_group hwmon_pwm_fan_attrgroup = {
741         .attrs = hwmon_pwm_fan_attributes,
742 };
743 #endif
744
745 static int
746 nouveau_hwmon_init(struct drm_device *dev)
747 {
748         struct nouveau_pm *pm = nouveau_pm(dev);
749         struct nouveau_drm *drm = nouveau_drm(dev);
750         struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
751         struct dcb_gpio_func func;
752
753 #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
754         struct device *hwmon_dev;
755         int ret = 0;
756
757         if (!pm->temp_get)
758                 return -ENODEV;
759
760         hwmon_dev = hwmon_device_register(&dev->pdev->dev);
761         if (IS_ERR(hwmon_dev)) {
762                 ret = PTR_ERR(hwmon_dev);
763                 NV_ERROR(drm, "Unable to register hwmon device: %d\n", ret);
764                 return ret;
765         }
766         dev_set_drvdata(hwmon_dev, dev);
767
768         /* default sysfs entries */
769         ret = sysfs_create_group(&dev->pdev->dev.kobj, &hwmon_attrgroup);
770         if (ret) {
771                 if (ret)
772                         goto error;
773         }
774
775         /* if the card has a pwm fan */
776         /*XXX: incorrect, need better detection for this, some boards have
777          *     the gpio entries for pwm fan control even when there's no
778          *     actual fan connected to it... therm table? */
779         if (nouveau_pwmfan_get(dev) >= 0) {
780                 ret = sysfs_create_group(&dev->pdev->dev.kobj,
781                                          &hwmon_pwm_fan_attrgroup);
782                 if (ret)
783                         goto error;
784         }
785
786         /* if the card can read the fan rpm */
787         if (!gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func)) {
788                 ret = sysfs_create_group(&dev->pdev->dev.kobj,
789                                          &hwmon_fan_rpm_attrgroup);
790                 if (ret)
791                         goto error;
792         }
793
794         pm->hwmon = hwmon_dev;
795
796         return 0;
797
798 error:
799         NV_ERROR(drm, "Unable to create some hwmon sysfs files: %d\n", ret);
800         hwmon_device_unregister(hwmon_dev);
801         pm->hwmon = NULL;
802         return ret;
803 #else
804         pm->hwmon = NULL;
805         return 0;
806 #endif
807 }
808
809 static void
810 nouveau_hwmon_fini(struct drm_device *dev)
811 {
812 #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
813         struct nouveau_pm *pm = nouveau_pm(dev);
814
815         if (pm->hwmon) {
816                 sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_attrgroup);
817                 sysfs_remove_group(&dev->pdev->dev.kobj,
818                                    &hwmon_pwm_fan_attrgroup);
819                 sysfs_remove_group(&dev->pdev->dev.kobj,
820                                    &hwmon_fan_rpm_attrgroup);
821
822                 hwmon_device_unregister(pm->hwmon);
823         }
824 #endif
825 }
826
827 #if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY)
828 static int
829 nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data)
830 {
831         struct nouveau_pm *pm = container_of(nb, struct nouveau_pm, acpi_nb);
832         struct nouveau_drm *drm = nouveau_drm(pm->dev);
833         struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
834
835         if (strcmp(entry->device_class, "ac_adapter") == 0) {
836                 bool ac = power_supply_is_system_supplied();
837
838                 NV_DEBUG(drm, "power supply changed: %s\n", ac ? "AC" : "DC");
839                 nouveau_pm_trigger(pm->dev);
840         }
841
842         return NOTIFY_OK;
843 }
844 #endif
845
846 int
847 nouveau_pm_init(struct drm_device *dev)
848 {
849         struct nouveau_device *device = nouveau_dev(dev);
850         struct nouveau_drm *drm = nouveau_drm(dev);
851         struct nouveau_pm *pm;
852         char info[256];
853         int ret, i;
854
855         pm = drm->pm = kzalloc(sizeof(*pm), GFP_KERNEL);
856         if (!pm)
857                 return -ENOMEM;
858
859         pm->dev = dev;
860
861         if (device->card_type < NV_40) {
862                 pm->clocks_get = nv04_pm_clocks_get;
863                 pm->clocks_pre = nv04_pm_clocks_pre;
864                 pm->clocks_set = nv04_pm_clocks_set;
865                 if (nouveau_gpio(drm->device)) {
866                         pm->voltage_get = nouveau_voltage_gpio_get;
867                         pm->voltage_set = nouveau_voltage_gpio_set;
868                 }
869         } else
870         if (device->card_type < NV_50) {
871                 pm->clocks_get = nv40_pm_clocks_get;
872                 pm->clocks_pre = nv40_pm_clocks_pre;
873                 pm->clocks_set = nv40_pm_clocks_set;
874                 pm->voltage_get = nouveau_voltage_gpio_get;
875                 pm->voltage_set = nouveau_voltage_gpio_set;
876                 pm->temp_get = nv40_temp_get;
877                 pm->pwm_get = nv40_pm_pwm_get;
878                 pm->pwm_set = nv40_pm_pwm_set;
879         } else
880         if (device->card_type < NV_C0) {
881                 if (device->chipset <  0xa3 ||
882                     device->chipset == 0xaa ||
883                     device->chipset == 0xac) {
884                         pm->clocks_get = nv50_pm_clocks_get;
885                         pm->clocks_pre = nv50_pm_clocks_pre;
886                         pm->clocks_set = nv50_pm_clocks_set;
887                 } else {
888                         pm->clocks_get = nva3_pm_clocks_get;
889                         pm->clocks_pre = nva3_pm_clocks_pre;
890                         pm->clocks_set = nva3_pm_clocks_set;
891                 }
892                 pm->voltage_get = nouveau_voltage_gpio_get;
893                 pm->voltage_set = nouveau_voltage_gpio_set;
894                 if (device->chipset == 0x50)
895                         pm->temp_get = nv40_temp_get;
896                 else
897                         pm->temp_get = nv84_temp_get;
898                 pm->pwm_get = nv50_pm_pwm_get;
899                 pm->pwm_set = nv50_pm_pwm_set;
900         } else
901         if (device->card_type < NV_E0) {
902                 pm->clocks_get = nvc0_pm_clocks_get;
903                 pm->clocks_pre = nvc0_pm_clocks_pre;
904                 pm->clocks_set = nvc0_pm_clocks_set;
905                 pm->voltage_get = nouveau_voltage_gpio_get;
906                 pm->voltage_set = nouveau_voltage_gpio_set;
907                 pm->temp_get = nv84_temp_get;
908                 if (device->card_type < NV_D0) {
909                         pm->pwm_get = nv50_pm_pwm_get;
910                         pm->pwm_set = nv50_pm_pwm_set;
911                 }
912         }
913
914
915         /* parse aux tables from vbios */
916         nouveau_volt_init(dev);
917         nouveau_temp_init(dev);
918
919         /* determine current ("boot") performance level */
920         ret = nouveau_pm_perflvl_get(dev, &pm->boot);
921         if (ret) {
922                 NV_ERROR(drm, "failed to determine boot perflvl\n");
923                 return ret;
924         }
925
926         strncpy(pm->boot.name, "boot", 4);
927         strncpy(pm->boot.profile.name, "boot", 4);
928         pm->boot.profile.func = &nouveau_pm_static_profile_func;
929
930         INIT_LIST_HEAD(&pm->profiles);
931         list_add(&pm->boot.profile.head, &pm->profiles);
932
933         pm->profile_ac = &pm->boot.profile;
934         pm->profile_dc = &pm->boot.profile;
935         pm->profile = &pm->boot.profile;
936         pm->cur = &pm->boot;
937
938         /* add performance levels from vbios */
939         nouveau_perf_init(dev);
940
941         /* display available performance levels */
942         NV_INFO(drm, "%d available performance level(s)\n", pm->nr_perflvl);
943         for (i = 0; i < pm->nr_perflvl; i++) {
944                 nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info));
945                 NV_INFO(drm, "%d:%s", pm->perflvl[i].id, info);
946         }
947
948         nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info));
949         NV_INFO(drm, "c:%s", info);
950
951         /* switch performance levels now if requested */
952         if (nouveau_perflvl != NULL)
953                 nouveau_pm_profile_set(dev, nouveau_perflvl);
954
955         /* determine the current fan speed */
956         pm->fan.percent = nouveau_pwmfan_get(dev);
957
958         nouveau_sysfs_init(dev);
959         nouveau_hwmon_init(dev);
960 #if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY)
961         pm->acpi_nb.notifier_call = nouveau_pm_acpi_event;
962         register_acpi_notifier(&pm->acpi_nb);
963 #endif
964
965         return 0;
966 }
967
968 void
969 nouveau_pm_fini(struct drm_device *dev)
970 {
971         struct nouveau_pm *pm = nouveau_pm(dev);
972         struct nouveau_pm_profile *profile, *tmp;
973
974         list_for_each_entry_safe(profile, tmp, &pm->profiles, head) {
975                 list_del(&profile->head);
976                 profile->func->destroy(profile);
977         }
978
979         if (pm->cur != &pm->boot)
980                 nouveau_pm_perflvl_set(dev, &pm->boot);
981
982         nouveau_temp_fini(dev);
983         nouveau_perf_fini(dev);
984         nouveau_volt_fini(dev);
985
986 #if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY)
987         unregister_acpi_notifier(&pm->acpi_nb);
988 #endif
989         nouveau_hwmon_fini(dev);
990         nouveau_sysfs_fini(dev);
991
992         nouveau_drm(dev)->pm = NULL;
993         kfree(pm);
994 }
995
996 void
997 nouveau_pm_resume(struct drm_device *dev)
998 {
999         struct nouveau_pm *pm = nouveau_pm(dev);
1000         struct nouveau_pm_level *perflvl;
1001
1002         if (!pm->cur || pm->cur == &pm->boot)
1003                 return;
1004
1005         perflvl = pm->cur;
1006         pm->cur = &pm->boot;
1007         nouveau_pm_perflvl_set(dev, perflvl);
1008         nouveau_pwmfan_set(dev, pm->fan.percent);
1009 }