nouveau_pm.c 31 KB

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