nouveau_pm.c 25 KB

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