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