trinity_dpm.c 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062
  1. /*
  2. * Copyright 2012 Advanced Micro Devices, 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. */
  23. #include <linux/pci.h>
  24. #include <linux/seq_file.h>
  25. #include "r600_dpm.h"
  26. #include "radeon.h"
  27. #include "radeon_asic.h"
  28. #include "trinity_dpm.h"
  29. #include "trinityd.h"
  30. #include "vce.h"
  31. #define TRINITY_MAX_DEEPSLEEP_DIVIDER_ID 5
  32. #define TRINITY_MINIMUM_ENGINE_CLOCK 800
  33. #define SCLK_MIN_DIV_INTV_SHIFT 12
  34. #define TRINITY_DISPCLK_BYPASS_THRESHOLD 10000
  35. #ifndef TRINITY_MGCG_SEQUENCE
  36. #define TRINITY_MGCG_SEQUENCE 100
  37. static const u32 trinity_mgcg_shls_default[] =
  38. {
  39. /* Register, Value, Mask */
  40. 0x0000802c, 0xc0000000, 0xffffffff,
  41. 0x00003fc4, 0xc0000000, 0xffffffff,
  42. 0x00005448, 0x00000100, 0xffffffff,
  43. 0x000055e4, 0x00000100, 0xffffffff,
  44. 0x0000160c, 0x00000100, 0xffffffff,
  45. 0x00008984, 0x06000100, 0xffffffff,
  46. 0x0000c164, 0x00000100, 0xffffffff,
  47. 0x00008a18, 0x00000100, 0xffffffff,
  48. 0x0000897c, 0x06000100, 0xffffffff,
  49. 0x00008b28, 0x00000100, 0xffffffff,
  50. 0x00009144, 0x00800200, 0xffffffff,
  51. 0x00009a60, 0x00000100, 0xffffffff,
  52. 0x00009868, 0x00000100, 0xffffffff,
  53. 0x00008d58, 0x00000100, 0xffffffff,
  54. 0x00009510, 0x00000100, 0xffffffff,
  55. 0x0000949c, 0x00000100, 0xffffffff,
  56. 0x00009654, 0x00000100, 0xffffffff,
  57. 0x00009030, 0x00000100, 0xffffffff,
  58. 0x00009034, 0x00000100, 0xffffffff,
  59. 0x00009038, 0x00000100, 0xffffffff,
  60. 0x0000903c, 0x00000100, 0xffffffff,
  61. 0x00009040, 0x00000100, 0xffffffff,
  62. 0x0000a200, 0x00000100, 0xffffffff,
  63. 0x0000a204, 0x00000100, 0xffffffff,
  64. 0x0000a208, 0x00000100, 0xffffffff,
  65. 0x0000a20c, 0x00000100, 0xffffffff,
  66. 0x00009744, 0x00000100, 0xffffffff,
  67. 0x00003f80, 0x00000100, 0xffffffff,
  68. 0x0000a210, 0x00000100, 0xffffffff,
  69. 0x0000a214, 0x00000100, 0xffffffff,
  70. 0x000004d8, 0x00000100, 0xffffffff,
  71. 0x00009664, 0x00000100, 0xffffffff,
  72. 0x00009698, 0x00000100, 0xffffffff,
  73. 0x000004d4, 0x00000200, 0xffffffff,
  74. 0x000004d0, 0x00000000, 0xffffffff,
  75. 0x000030cc, 0x00000104, 0xffffffff,
  76. 0x0000d0c0, 0x00000100, 0xffffffff,
  77. 0x0000d8c0, 0x00000100, 0xffffffff,
  78. 0x0000951c, 0x00010000, 0xffffffff,
  79. 0x00009160, 0x00030002, 0xffffffff,
  80. 0x00009164, 0x00050004, 0xffffffff,
  81. 0x00009168, 0x00070006, 0xffffffff,
  82. 0x00009178, 0x00070000, 0xffffffff,
  83. 0x0000917c, 0x00030002, 0xffffffff,
  84. 0x00009180, 0x00050004, 0xffffffff,
  85. 0x0000918c, 0x00010006, 0xffffffff,
  86. 0x00009190, 0x00090008, 0xffffffff,
  87. 0x00009194, 0x00070000, 0xffffffff,
  88. 0x00009198, 0x00030002, 0xffffffff,
  89. 0x0000919c, 0x00050004, 0xffffffff,
  90. 0x000091a8, 0x00010006, 0xffffffff,
  91. 0x000091ac, 0x00090008, 0xffffffff,
  92. 0x000091b0, 0x00070000, 0xffffffff,
  93. 0x000091b4, 0x00030002, 0xffffffff,
  94. 0x000091b8, 0x00050004, 0xffffffff,
  95. 0x000091c4, 0x00010006, 0xffffffff,
  96. 0x000091c8, 0x00090008, 0xffffffff,
  97. 0x000091cc, 0x00070000, 0xffffffff,
  98. 0x000091d0, 0x00030002, 0xffffffff,
  99. 0x000091d4, 0x00050004, 0xffffffff,
  100. 0x000091e0, 0x00010006, 0xffffffff,
  101. 0x000091e4, 0x00090008, 0xffffffff,
  102. 0x000091e8, 0x00000000, 0xffffffff,
  103. 0x000091ec, 0x00070000, 0xffffffff,
  104. 0x000091f0, 0x00030002, 0xffffffff,
  105. 0x000091f4, 0x00050004, 0xffffffff,
  106. 0x00009200, 0x00010006, 0xffffffff,
  107. 0x00009204, 0x00090008, 0xffffffff,
  108. 0x00009208, 0x00070000, 0xffffffff,
  109. 0x0000920c, 0x00030002, 0xffffffff,
  110. 0x00009210, 0x00050004, 0xffffffff,
  111. 0x0000921c, 0x00010006, 0xffffffff,
  112. 0x00009220, 0x00090008, 0xffffffff,
  113. 0x00009294, 0x00000000, 0xffffffff
  114. };
  115. #endif
  116. #ifndef TRINITY_SYSLS_SEQUENCE
  117. #define TRINITY_SYSLS_SEQUENCE 100
  118. static const u32 trinity_sysls_disable[] =
  119. {
  120. /* Register, Value, Mask */
  121. 0x0000d0c0, 0x00000000, 0xffffffff,
  122. 0x0000d8c0, 0x00000000, 0xffffffff,
  123. 0x000055e8, 0x00000000, 0xffffffff,
  124. 0x0000d0bc, 0x00000000, 0xffffffff,
  125. 0x0000d8bc, 0x00000000, 0xffffffff,
  126. 0x000015c0, 0x00041401, 0xffffffff,
  127. 0x0000264c, 0x00040400, 0xffffffff,
  128. 0x00002648, 0x00040400, 0xffffffff,
  129. 0x00002650, 0x00040400, 0xffffffff,
  130. 0x000020b8, 0x00040400, 0xffffffff,
  131. 0x000020bc, 0x00040400, 0xffffffff,
  132. 0x000020c0, 0x00040c80, 0xffffffff,
  133. 0x0000f4a0, 0x000000c0, 0xffffffff,
  134. 0x0000f4a4, 0x00680000, 0xffffffff,
  135. 0x00002f50, 0x00000404, 0xffffffff,
  136. 0x000004c8, 0x00000001, 0xffffffff,
  137. 0x0000641c, 0x00007ffd, 0xffffffff,
  138. 0x00000c7c, 0x0000ff00, 0xffffffff,
  139. 0x00006dfc, 0x0000007f, 0xffffffff
  140. };
  141. static const u32 trinity_sysls_enable[] =
  142. {
  143. /* Register, Value, Mask */
  144. 0x000055e8, 0x00000001, 0xffffffff,
  145. 0x0000d0bc, 0x00000100, 0xffffffff,
  146. 0x0000d8bc, 0x00000100, 0xffffffff,
  147. 0x000015c0, 0x000c1401, 0xffffffff,
  148. 0x0000264c, 0x000c0400, 0xffffffff,
  149. 0x00002648, 0x000c0400, 0xffffffff,
  150. 0x00002650, 0x000c0400, 0xffffffff,
  151. 0x000020b8, 0x000c0400, 0xffffffff,
  152. 0x000020bc, 0x000c0400, 0xffffffff,
  153. 0x000020c0, 0x000c0c80, 0xffffffff,
  154. 0x0000f4a0, 0x000000c0, 0xffffffff,
  155. 0x0000f4a4, 0x00680fff, 0xffffffff,
  156. 0x00002f50, 0x00000903, 0xffffffff,
  157. 0x000004c8, 0x00000000, 0xffffffff,
  158. 0x0000641c, 0x00000000, 0xffffffff,
  159. 0x00000c7c, 0x00000000, 0xffffffff,
  160. 0x00006dfc, 0x00000000, 0xffffffff
  161. };
  162. #endif
  163. static const u32 trinity_override_mgpg_sequences[] =
  164. {
  165. /* Register, Value */
  166. 0x00000200, 0xE030032C,
  167. 0x00000204, 0x00000FFF,
  168. 0x00000200, 0xE0300058,
  169. 0x00000204, 0x00030301,
  170. 0x00000200, 0xE0300054,
  171. 0x00000204, 0x500010FF,
  172. 0x00000200, 0xE0300074,
  173. 0x00000204, 0x00030301,
  174. 0x00000200, 0xE0300070,
  175. 0x00000204, 0x500010FF,
  176. 0x00000200, 0xE0300090,
  177. 0x00000204, 0x00030301,
  178. 0x00000200, 0xE030008C,
  179. 0x00000204, 0x500010FF,
  180. 0x00000200, 0xE03000AC,
  181. 0x00000204, 0x00030301,
  182. 0x00000200, 0xE03000A8,
  183. 0x00000204, 0x500010FF,
  184. 0x00000200, 0xE03000C8,
  185. 0x00000204, 0x00030301,
  186. 0x00000200, 0xE03000C4,
  187. 0x00000204, 0x500010FF,
  188. 0x00000200, 0xE03000E4,
  189. 0x00000204, 0x00030301,
  190. 0x00000200, 0xE03000E0,
  191. 0x00000204, 0x500010FF,
  192. 0x00000200, 0xE0300100,
  193. 0x00000204, 0x00030301,
  194. 0x00000200, 0xE03000FC,
  195. 0x00000204, 0x500010FF,
  196. 0x00000200, 0xE0300058,
  197. 0x00000204, 0x00030303,
  198. 0x00000200, 0xE0300054,
  199. 0x00000204, 0x600010FF,
  200. 0x00000200, 0xE0300074,
  201. 0x00000204, 0x00030303,
  202. 0x00000200, 0xE0300070,
  203. 0x00000204, 0x600010FF,
  204. 0x00000200, 0xE0300090,
  205. 0x00000204, 0x00030303,
  206. 0x00000200, 0xE030008C,
  207. 0x00000204, 0x600010FF,
  208. 0x00000200, 0xE03000AC,
  209. 0x00000204, 0x00030303,
  210. 0x00000200, 0xE03000A8,
  211. 0x00000204, 0x600010FF,
  212. 0x00000200, 0xE03000C8,
  213. 0x00000204, 0x00030303,
  214. 0x00000200, 0xE03000C4,
  215. 0x00000204, 0x600010FF,
  216. 0x00000200, 0xE03000E4,
  217. 0x00000204, 0x00030303,
  218. 0x00000200, 0xE03000E0,
  219. 0x00000204, 0x600010FF,
  220. 0x00000200, 0xE0300100,
  221. 0x00000204, 0x00030303,
  222. 0x00000200, 0xE03000FC,
  223. 0x00000204, 0x600010FF,
  224. 0x00000200, 0xE0300058,
  225. 0x00000204, 0x00030303,
  226. 0x00000200, 0xE0300054,
  227. 0x00000204, 0x700010FF,
  228. 0x00000200, 0xE0300074,
  229. 0x00000204, 0x00030303,
  230. 0x00000200, 0xE0300070,
  231. 0x00000204, 0x700010FF,
  232. 0x00000200, 0xE0300090,
  233. 0x00000204, 0x00030303,
  234. 0x00000200, 0xE030008C,
  235. 0x00000204, 0x700010FF,
  236. 0x00000200, 0xE03000AC,
  237. 0x00000204, 0x00030303,
  238. 0x00000200, 0xE03000A8,
  239. 0x00000204, 0x700010FF,
  240. 0x00000200, 0xE03000C8,
  241. 0x00000204, 0x00030303,
  242. 0x00000200, 0xE03000C4,
  243. 0x00000204, 0x700010FF,
  244. 0x00000200, 0xE03000E4,
  245. 0x00000204, 0x00030303,
  246. 0x00000200, 0xE03000E0,
  247. 0x00000204, 0x700010FF,
  248. 0x00000200, 0xE0300100,
  249. 0x00000204, 0x00030303,
  250. 0x00000200, 0xE03000FC,
  251. 0x00000204, 0x700010FF,
  252. 0x00000200, 0xE0300058,
  253. 0x00000204, 0x00010303,
  254. 0x00000200, 0xE0300054,
  255. 0x00000204, 0x800010FF,
  256. 0x00000200, 0xE0300074,
  257. 0x00000204, 0x00010303,
  258. 0x00000200, 0xE0300070,
  259. 0x00000204, 0x800010FF,
  260. 0x00000200, 0xE0300090,
  261. 0x00000204, 0x00010303,
  262. 0x00000200, 0xE030008C,
  263. 0x00000204, 0x800010FF,
  264. 0x00000200, 0xE03000AC,
  265. 0x00000204, 0x00010303,
  266. 0x00000200, 0xE03000A8,
  267. 0x00000204, 0x800010FF,
  268. 0x00000200, 0xE03000C4,
  269. 0x00000204, 0x800010FF,
  270. 0x00000200, 0xE03000C8,
  271. 0x00000204, 0x00010303,
  272. 0x00000200, 0xE03000E4,
  273. 0x00000204, 0x00010303,
  274. 0x00000200, 0xE03000E0,
  275. 0x00000204, 0x800010FF,
  276. 0x00000200, 0xE0300100,
  277. 0x00000204, 0x00010303,
  278. 0x00000200, 0xE03000FC,
  279. 0x00000204, 0x800010FF,
  280. 0x00000200, 0x0001f198,
  281. 0x00000204, 0x0003ffff,
  282. 0x00000200, 0x0001f19C,
  283. 0x00000204, 0x3fffffff,
  284. 0x00000200, 0xE030032C,
  285. 0x00000204, 0x00000000,
  286. };
  287. static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
  288. const u32 *seq, u32 count);
  289. static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev);
  290. static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
  291. struct radeon_ps *new_rps,
  292. struct radeon_ps *old_rps);
  293. static struct trinity_ps *trinity_get_ps(struct radeon_ps *rps)
  294. {
  295. struct trinity_ps *ps = rps->ps_priv;
  296. return ps;
  297. }
  298. static struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev)
  299. {
  300. struct trinity_power_info *pi = rdev->pm.dpm.priv;
  301. return pi;
  302. }
  303. static void trinity_gfx_powergating_initialize(struct radeon_device *rdev)
  304. {
  305. struct trinity_power_info *pi = trinity_get_pi(rdev);
  306. u32 p, u;
  307. u32 value;
  308. struct atom_clock_dividers dividers;
  309. u32 xclk = radeon_get_xclk(rdev);
  310. u32 sssd = 1;
  311. int ret;
  312. u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT;
  313. ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
  314. 25000, false, &dividers);
  315. if (ret)
  316. return;
  317. value = RREG32_SMC(GFX_POWER_GATING_CNTL);
  318. value &= ~(SSSD_MASK | PDS_DIV_MASK);
  319. if (sssd)
  320. value |= SSSD(1);
  321. value |= PDS_DIV(dividers.post_div);
  322. WREG32_SMC(GFX_POWER_GATING_CNTL, value);
  323. r600_calculate_u_and_p(500, xclk, 16, &p, &u);
  324. WREG32(CG_PG_CTRL, SP(p) | SU(u));
  325. WREG32_P(CG_GIPOTS, CG_GIPOT(p), ~CG_GIPOT_MASK);
  326. /* XXX double check hw_rev */
  327. if (pi->override_dynamic_mgpg && (hw_rev == 0))
  328. trinity_override_dynamic_mg_powergating(rdev);
  329. }
  330. #define CGCG_CGTT_LOCAL0_MASK 0xFFFF33FF
  331. #define CGCG_CGTT_LOCAL1_MASK 0xFFFB0FFE
  332. #define CGTS_SM_CTRL_REG_DISABLE 0x00600000
  333. #define CGTS_SM_CTRL_REG_ENABLE 0x96944200
  334. static void trinity_mg_clockgating_enable(struct radeon_device *rdev,
  335. bool enable)
  336. {
  337. u32 local0;
  338. u32 local1;
  339. if (enable) {
  340. local0 = RREG32_CG(CG_CGTT_LOCAL_0);
  341. local1 = RREG32_CG(CG_CGTT_LOCAL_1);
  342. WREG32_CG(CG_CGTT_LOCAL_0,
  343. (0x00380000 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
  344. WREG32_CG(CG_CGTT_LOCAL_1,
  345. (0x0E000000 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
  346. WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_ENABLE);
  347. } else {
  348. WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_DISABLE);
  349. local0 = RREG32_CG(CG_CGTT_LOCAL_0);
  350. local1 = RREG32_CG(CG_CGTT_LOCAL_1);
  351. WREG32_CG(CG_CGTT_LOCAL_0,
  352. CGCG_CGTT_LOCAL0_MASK | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
  353. WREG32_CG(CG_CGTT_LOCAL_1,
  354. CGCG_CGTT_LOCAL1_MASK | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
  355. }
  356. }
  357. static void trinity_mg_clockgating_initialize(struct radeon_device *rdev)
  358. {
  359. u32 count;
  360. const u32 *seq = NULL;
  361. seq = &trinity_mgcg_shls_default[0];
  362. count = sizeof(trinity_mgcg_shls_default) / (3 * sizeof(u32));
  363. trinity_program_clk_gating_hw_sequence(rdev, seq, count);
  364. }
  365. static void trinity_gfx_clockgating_enable(struct radeon_device *rdev,
  366. bool enable)
  367. {
  368. if (enable) {
  369. WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
  370. } else {
  371. WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
  372. WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
  373. WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
  374. RREG32(GB_ADDR_CONFIG);
  375. }
  376. }
  377. static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
  378. const u32 *seq, u32 count)
  379. {
  380. u32 i, length = count * 3;
  381. for (i = 0; i < length; i += 3)
  382. WREG32_P(seq[i], seq[i+1], ~seq[i+2]);
  383. }
  384. static void trinity_program_override_mgpg_sequences(struct radeon_device *rdev,
  385. const u32 *seq, u32 count)
  386. {
  387. u32 i, length = count * 2;
  388. for (i = 0; i < length; i += 2)
  389. WREG32(seq[i], seq[i+1]);
  390. }
  391. static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev)
  392. {
  393. u32 count;
  394. const u32 *seq = NULL;
  395. seq = &trinity_override_mgpg_sequences[0];
  396. count = sizeof(trinity_override_mgpg_sequences) / (2 * sizeof(u32));
  397. trinity_program_override_mgpg_sequences(rdev, seq, count);
  398. }
  399. static void trinity_ls_clockgating_enable(struct radeon_device *rdev,
  400. bool enable)
  401. {
  402. u32 count;
  403. const u32 *seq = NULL;
  404. if (enable) {
  405. seq = &trinity_sysls_enable[0];
  406. count = sizeof(trinity_sysls_enable) / (3 * sizeof(u32));
  407. } else {
  408. seq = &trinity_sysls_disable[0];
  409. count = sizeof(trinity_sysls_disable) / (3 * sizeof(u32));
  410. }
  411. trinity_program_clk_gating_hw_sequence(rdev, seq, count);
  412. }
  413. static void trinity_gfx_powergating_enable(struct radeon_device *rdev,
  414. bool enable)
  415. {
  416. if (enable) {
  417. if (RREG32_SMC(CC_SMU_TST_EFUSE1_MISC) & RB_BACKEND_DISABLE_MASK)
  418. WREG32_SMC(SMU_SCRATCH_A, (RREG32_SMC(SMU_SCRATCH_A) | 0x01));
  419. WREG32_P(SCLK_PWRMGT_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN);
  420. } else {
  421. WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_PWR_DOWN_EN);
  422. RREG32(GB_ADDR_CONFIG);
  423. }
  424. }
  425. static void trinity_gfx_dynamic_mgpg_enable(struct radeon_device *rdev,
  426. bool enable)
  427. {
  428. u32 value;
  429. if (enable) {
  430. value = RREG32_SMC(PM_I_CNTL_1);
  431. value &= ~DS_PG_CNTL_MASK;
  432. value |= DS_PG_CNTL(1);
  433. WREG32_SMC(PM_I_CNTL_1, value);
  434. value = RREG32_SMC(SMU_S_PG_CNTL);
  435. value &= ~DS_PG_EN_MASK;
  436. value |= DS_PG_EN(1);
  437. WREG32_SMC(SMU_S_PG_CNTL, value);
  438. } else {
  439. value = RREG32_SMC(SMU_S_PG_CNTL);
  440. value &= ~DS_PG_EN_MASK;
  441. WREG32_SMC(SMU_S_PG_CNTL, value);
  442. value = RREG32_SMC(PM_I_CNTL_1);
  443. value &= ~DS_PG_CNTL_MASK;
  444. WREG32_SMC(PM_I_CNTL_1, value);
  445. }
  446. trinity_gfx_dynamic_mgpg_config(rdev);
  447. }
  448. static void trinity_enable_clock_power_gating(struct radeon_device *rdev)
  449. {
  450. struct trinity_power_info *pi = trinity_get_pi(rdev);
  451. if (pi->enable_gfx_clock_gating)
  452. sumo_gfx_clockgating_initialize(rdev);
  453. if (pi->enable_mg_clock_gating)
  454. trinity_mg_clockgating_initialize(rdev);
  455. if (pi->enable_gfx_power_gating)
  456. trinity_gfx_powergating_initialize(rdev);
  457. if (pi->enable_mg_clock_gating) {
  458. trinity_ls_clockgating_enable(rdev, true);
  459. trinity_mg_clockgating_enable(rdev, true);
  460. }
  461. if (pi->enable_gfx_clock_gating)
  462. trinity_gfx_clockgating_enable(rdev, true);
  463. if (pi->enable_gfx_dynamic_mgpg)
  464. trinity_gfx_dynamic_mgpg_enable(rdev, true);
  465. if (pi->enable_gfx_power_gating)
  466. trinity_gfx_powergating_enable(rdev, true);
  467. }
  468. static void trinity_disable_clock_power_gating(struct radeon_device *rdev)
  469. {
  470. struct trinity_power_info *pi = trinity_get_pi(rdev);
  471. if (pi->enable_gfx_power_gating)
  472. trinity_gfx_powergating_enable(rdev, false);
  473. if (pi->enable_gfx_dynamic_mgpg)
  474. trinity_gfx_dynamic_mgpg_enable(rdev, false);
  475. if (pi->enable_gfx_clock_gating)
  476. trinity_gfx_clockgating_enable(rdev, false);
  477. if (pi->enable_mg_clock_gating) {
  478. trinity_mg_clockgating_enable(rdev, false);
  479. trinity_ls_clockgating_enable(rdev, false);
  480. }
  481. }
  482. static void trinity_set_divider_value(struct radeon_device *rdev,
  483. u32 index, u32 sclk)
  484. {
  485. struct atom_clock_dividers dividers;
  486. int ret;
  487. u32 value;
  488. u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
  489. ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
  490. sclk, false, &dividers);
  491. if (ret)
  492. return;
  493. value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
  494. value &= ~CLK_DIVIDER_MASK;
  495. value |= CLK_DIVIDER(dividers.post_div);
  496. WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
  497. ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
  498. sclk/2, false, &dividers);
  499. if (ret)
  500. return;
  501. value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix);
  502. value &= ~PD_SCLK_DIVIDER_MASK;
  503. value |= PD_SCLK_DIVIDER(dividers.post_div);
  504. WREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix, value);
  505. }
  506. static void trinity_set_ds_dividers(struct radeon_device *rdev,
  507. u32 index, u32 divider)
  508. {
  509. u32 value;
  510. u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
  511. value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
  512. value &= ~DS_DIV_MASK;
  513. value |= DS_DIV(divider);
  514. WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
  515. }
  516. static void trinity_set_ss_dividers(struct radeon_device *rdev,
  517. u32 index, u32 divider)
  518. {
  519. u32 value;
  520. u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
  521. value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
  522. value &= ~DS_SH_DIV_MASK;
  523. value |= DS_SH_DIV(divider);
  524. WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
  525. }
  526. static void trinity_set_vid(struct radeon_device *rdev, u32 index, u32 vid)
  527. {
  528. struct trinity_power_info *pi = trinity_get_pi(rdev);
  529. u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid);
  530. u32 value;
  531. u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
  532. value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
  533. value &= ~VID_MASK;
  534. value |= VID(vid_7bit);
  535. WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
  536. value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
  537. value &= ~LVRT_MASK;
  538. value |= LVRT(0);
  539. WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
  540. }
  541. static void trinity_set_allos_gnb_slow(struct radeon_device *rdev,
  542. u32 index, u32 gnb_slow)
  543. {
  544. u32 value;
  545. u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
  546. value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
  547. value &= ~GNB_SLOW_MASK;
  548. value |= GNB_SLOW(gnb_slow);
  549. WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
  550. }
  551. static void trinity_set_force_nbp_state(struct radeon_device *rdev,
  552. u32 index, u32 force_nbp_state)
  553. {
  554. u32 value;
  555. u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
  556. value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
  557. value &= ~FORCE_NBPS1_MASK;
  558. value |= FORCE_NBPS1(force_nbp_state);
  559. WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
  560. }
  561. static void trinity_set_display_wm(struct radeon_device *rdev,
  562. u32 index, u32 wm)
  563. {
  564. u32 value;
  565. u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
  566. value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
  567. value &= ~DISPLAY_WM_MASK;
  568. value |= DISPLAY_WM(wm);
  569. WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
  570. }
  571. static void trinity_set_vce_wm(struct radeon_device *rdev,
  572. u32 index, u32 wm)
  573. {
  574. u32 value;
  575. u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
  576. value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
  577. value &= ~VCE_WM_MASK;
  578. value |= VCE_WM(wm);
  579. WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
  580. }
  581. static void trinity_set_at(struct radeon_device *rdev,
  582. u32 index, u32 at)
  583. {
  584. u32 value;
  585. u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
  586. value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix);
  587. value &= ~AT_MASK;
  588. value |= AT(at);
  589. WREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix, value);
  590. }
  591. static void trinity_program_power_level(struct radeon_device *rdev,
  592. struct trinity_pl *pl, u32 index)
  593. {
  594. struct trinity_power_info *pi = trinity_get_pi(rdev);
  595. if (index >= SUMO_MAX_HARDWARE_POWERLEVELS)
  596. return;
  597. trinity_set_divider_value(rdev, index, pl->sclk);
  598. trinity_set_vid(rdev, index, pl->vddc_index);
  599. trinity_set_ss_dividers(rdev, index, pl->ss_divider_index);
  600. trinity_set_ds_dividers(rdev, index, pl->ds_divider_index);
  601. trinity_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow);
  602. trinity_set_force_nbp_state(rdev, index, pl->force_nbp_state);
  603. trinity_set_display_wm(rdev, index, pl->display_wm);
  604. trinity_set_vce_wm(rdev, index, pl->vce_wm);
  605. trinity_set_at(rdev, index, pi->at[index]);
  606. }
  607. static void trinity_power_level_enable_disable(struct radeon_device *rdev,
  608. u32 index, bool enable)
  609. {
  610. u32 value;
  611. u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
  612. value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
  613. value &= ~STATE_VALID_MASK;
  614. if (enable)
  615. value |= STATE_VALID(1);
  616. WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
  617. }
  618. static bool trinity_dpm_enabled(struct radeon_device *rdev)
  619. {
  620. if (RREG32_SMC(SMU_SCLK_DPM_CNTL) & SCLK_DPM_EN(1))
  621. return true;
  622. else
  623. return false;
  624. }
  625. static void trinity_start_dpm(struct radeon_device *rdev)
  626. {
  627. u32 value = RREG32_SMC(SMU_SCLK_DPM_CNTL);
  628. value &= ~(SCLK_DPM_EN_MASK | SCLK_DPM_BOOT_STATE_MASK | VOLTAGE_CHG_EN_MASK);
  629. value |= SCLK_DPM_EN(1) | SCLK_DPM_BOOT_STATE(0) | VOLTAGE_CHG_EN(1);
  630. WREG32_SMC(SMU_SCLK_DPM_CNTL, value);
  631. WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
  632. WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~EN);
  633. trinity_dpm_config(rdev, true);
  634. }
  635. static void trinity_wait_for_dpm_enabled(struct radeon_device *rdev)
  636. {
  637. int i;
  638. for (i = 0; i < rdev->usec_timeout; i++) {
  639. if (RREG32(SCLK_PWRMGT_CNTL) & DYNAMIC_PM_EN)
  640. break;
  641. udelay(1);
  642. }
  643. for (i = 0; i < rdev->usec_timeout; i++) {
  644. if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_STATE_MASK) == 0)
  645. break;
  646. udelay(1);
  647. }
  648. for (i = 0; i < rdev->usec_timeout; i++) {
  649. if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
  650. break;
  651. udelay(1);
  652. }
  653. }
  654. static void trinity_stop_dpm(struct radeon_device *rdev)
  655. {
  656. u32 sclk_dpm_cntl;
  657. WREG32_P(CG_CG_VOLTAGE_CNTL, EN, ~EN);
  658. sclk_dpm_cntl = RREG32_SMC(SMU_SCLK_DPM_CNTL);
  659. sclk_dpm_cntl &= ~(SCLK_DPM_EN_MASK | VOLTAGE_CHG_EN_MASK);
  660. WREG32_SMC(SMU_SCLK_DPM_CNTL, sclk_dpm_cntl);
  661. trinity_dpm_config(rdev, false);
  662. }
  663. static void trinity_start_am(struct radeon_device *rdev)
  664. {
  665. WREG32_P(SCLK_PWRMGT_CNTL, 0, ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
  666. }
  667. static void trinity_reset_am(struct radeon_device *rdev)
  668. {
  669. WREG32_P(SCLK_PWRMGT_CNTL, RESET_SCLK_CNT | RESET_BUSY_CNT,
  670. ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
  671. }
  672. static void trinity_wait_for_level_0(struct radeon_device *rdev)
  673. {
  674. int i;
  675. for (i = 0; i < rdev->usec_timeout; i++) {
  676. if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
  677. break;
  678. udelay(1);
  679. }
  680. }
  681. static void trinity_enable_power_level_0(struct radeon_device *rdev)
  682. {
  683. trinity_power_level_enable_disable(rdev, 0, true);
  684. }
  685. static void trinity_force_level_0(struct radeon_device *rdev)
  686. {
  687. trinity_dpm_force_state(rdev, 0);
  688. }
  689. static void trinity_unforce_levels(struct radeon_device *rdev)
  690. {
  691. trinity_dpm_no_forced_level(rdev);
  692. }
  693. static void trinity_program_power_levels_0_to_n(struct radeon_device *rdev,
  694. struct radeon_ps *new_rps,
  695. struct radeon_ps *old_rps)
  696. {
  697. struct trinity_ps *new_ps = trinity_get_ps(new_rps);
  698. struct trinity_ps *old_ps = trinity_get_ps(old_rps);
  699. u32 i;
  700. u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels;
  701. for (i = 0; i < new_ps->num_levels; i++) {
  702. trinity_program_power_level(rdev, &new_ps->levels[i], i);
  703. trinity_power_level_enable_disable(rdev, i, true);
  704. }
  705. for (i = new_ps->num_levels; i < n_current_state_levels; i++)
  706. trinity_power_level_enable_disable(rdev, i, false);
  707. }
  708. static void trinity_program_bootup_state(struct radeon_device *rdev)
  709. {
  710. struct trinity_power_info *pi = trinity_get_pi(rdev);
  711. u32 i;
  712. trinity_program_power_level(rdev, &pi->boot_pl, 0);
  713. trinity_power_level_enable_disable(rdev, 0, true);
  714. for (i = 1; i < 8; i++)
  715. trinity_power_level_enable_disable(rdev, i, false);
  716. }
  717. static void trinity_setup_uvd_clock_table(struct radeon_device *rdev,
  718. struct radeon_ps *rps)
  719. {
  720. struct trinity_ps *ps = trinity_get_ps(rps);
  721. u32 uvdstates = (ps->vclk_low_divider |
  722. ps->vclk_high_divider << 8 |
  723. ps->dclk_low_divider << 16 |
  724. ps->dclk_high_divider << 24);
  725. WREG32_SMC(SMU_UVD_DPM_STATES, uvdstates);
  726. }
  727. static void trinity_setup_uvd_dpm_interval(struct radeon_device *rdev,
  728. u32 interval)
  729. {
  730. u32 p, u;
  731. u32 tp = RREG32_SMC(PM_TP);
  732. u32 val;
  733. u32 xclk = radeon_get_xclk(rdev);
  734. r600_calculate_u_and_p(interval, xclk, 16, &p, &u);
  735. val = (p + tp - 1) / tp;
  736. WREG32_SMC(SMU_UVD_DPM_CNTL, val);
  737. }
  738. static bool trinity_uvd_clocks_zero(struct radeon_ps *rps)
  739. {
  740. if ((rps->vclk == 0) && (rps->dclk == 0))
  741. return true;
  742. else
  743. return false;
  744. }
  745. static bool trinity_uvd_clocks_equal(struct radeon_ps *rps1,
  746. struct radeon_ps *rps2)
  747. {
  748. struct trinity_ps *ps1 = trinity_get_ps(rps1);
  749. struct trinity_ps *ps2 = trinity_get_ps(rps2);
  750. if ((rps1->vclk == rps2->vclk) &&
  751. (rps1->dclk == rps2->dclk) &&
  752. (ps1->vclk_low_divider == ps2->vclk_low_divider) &&
  753. (ps1->vclk_high_divider == ps2->vclk_high_divider) &&
  754. (ps1->dclk_low_divider == ps2->dclk_low_divider) &&
  755. (ps1->dclk_high_divider == ps2->dclk_high_divider))
  756. return true;
  757. else
  758. return false;
  759. }
  760. static void trinity_setup_uvd_clocks(struct radeon_device *rdev,
  761. struct radeon_ps *new_rps,
  762. struct radeon_ps *old_rps)
  763. {
  764. struct trinity_power_info *pi = trinity_get_pi(rdev);
  765. if (pi->enable_gfx_power_gating) {
  766. trinity_gfx_powergating_enable(rdev, false);
  767. }
  768. if (pi->uvd_dpm) {
  769. if (trinity_uvd_clocks_zero(new_rps) &&
  770. !trinity_uvd_clocks_zero(old_rps)) {
  771. trinity_setup_uvd_dpm_interval(rdev, 0);
  772. } else if (!trinity_uvd_clocks_zero(new_rps)) {
  773. trinity_setup_uvd_clock_table(rdev, new_rps);
  774. if (trinity_uvd_clocks_zero(old_rps)) {
  775. u32 tmp = RREG32(CG_MISC_REG);
  776. tmp &= 0xfffffffd;
  777. WREG32(CG_MISC_REG, tmp);
  778. radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
  779. trinity_setup_uvd_dpm_interval(rdev, 3000);
  780. }
  781. }
  782. trinity_uvd_dpm_config(rdev);
  783. } else {
  784. if (trinity_uvd_clocks_zero(new_rps) ||
  785. trinity_uvd_clocks_equal(new_rps, old_rps))
  786. return;
  787. radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
  788. }
  789. if (pi->enable_gfx_power_gating) {
  790. trinity_gfx_powergating_enable(rdev, true);
  791. }
  792. }
  793. static void trinity_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
  794. struct radeon_ps *new_rps,
  795. struct radeon_ps *old_rps)
  796. {
  797. struct trinity_ps *new_ps = trinity_get_ps(new_rps);
  798. struct trinity_ps *current_ps = trinity_get_ps(new_rps);
  799. if (new_ps->levels[new_ps->num_levels - 1].sclk >=
  800. current_ps->levels[current_ps->num_levels - 1].sclk)
  801. return;
  802. trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
  803. }
  804. static void trinity_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
  805. struct radeon_ps *new_rps,
  806. struct radeon_ps *old_rps)
  807. {
  808. struct trinity_ps *new_ps = trinity_get_ps(new_rps);
  809. struct trinity_ps *current_ps = trinity_get_ps(old_rps);
  810. if (new_ps->levels[new_ps->num_levels - 1].sclk <
  811. current_ps->levels[current_ps->num_levels - 1].sclk)
  812. return;
  813. trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
  814. }
  815. static void trinity_set_vce_clock(struct radeon_device *rdev,
  816. struct radeon_ps *new_rps,
  817. struct radeon_ps *old_rps)
  818. {
  819. if ((old_rps->evclk != new_rps->evclk) ||
  820. (old_rps->ecclk != new_rps->ecclk)) {
  821. /* turn the clocks on when encoding, off otherwise */
  822. if (new_rps->evclk || new_rps->ecclk)
  823. vce_v1_0_enable_mgcg(rdev, false);
  824. else
  825. vce_v1_0_enable_mgcg(rdev, true);
  826. radeon_set_vce_clocks(rdev, new_rps->evclk, new_rps->ecclk);
  827. }
  828. }
  829. static void trinity_program_ttt(struct radeon_device *rdev)
  830. {
  831. struct trinity_power_info *pi = trinity_get_pi(rdev);
  832. u32 value = RREG32_SMC(SMU_SCLK_DPM_TTT);
  833. value &= ~(HT_MASK | LT_MASK);
  834. value |= HT((pi->thermal_auto_throttling + 49) * 8);
  835. value |= LT((pi->thermal_auto_throttling + 49 - pi->sys_info.htc_hyst_lmt) * 8);
  836. WREG32_SMC(SMU_SCLK_DPM_TTT, value);
  837. }
  838. static void trinity_enable_att(struct radeon_device *rdev)
  839. {
  840. u32 value = RREG32_SMC(SMU_SCLK_DPM_TT_CNTL);
  841. value &= ~SCLK_TT_EN_MASK;
  842. value |= SCLK_TT_EN(1);
  843. WREG32_SMC(SMU_SCLK_DPM_TT_CNTL, value);
  844. }
  845. static void trinity_program_sclk_dpm(struct radeon_device *rdev)
  846. {
  847. u32 p, u;
  848. u32 tp = RREG32_SMC(PM_TP);
  849. u32 ni;
  850. u32 xclk = radeon_get_xclk(rdev);
  851. u32 value;
  852. r600_calculate_u_and_p(400, xclk, 16, &p, &u);
  853. ni = (p + tp - 1) / tp;
  854. value = RREG32_SMC(PM_I_CNTL_1);
  855. value &= ~SCLK_DPM_MASK;
  856. value |= SCLK_DPM(ni);
  857. WREG32_SMC(PM_I_CNTL_1, value);
  858. }
  859. static int trinity_set_thermal_temperature_range(struct radeon_device *rdev,
  860. int min_temp, int max_temp)
  861. {
  862. int low_temp = 0 * 1000;
  863. int high_temp = 255 * 1000;
  864. if (low_temp < min_temp)
  865. low_temp = min_temp;
  866. if (high_temp > max_temp)
  867. high_temp = max_temp;
  868. if (high_temp < low_temp) {
  869. DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
  870. return -EINVAL;
  871. }
  872. WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK);
  873. WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK);
  874. rdev->pm.dpm.thermal.min_temp = low_temp;
  875. rdev->pm.dpm.thermal.max_temp = high_temp;
  876. return 0;
  877. }
  878. static void trinity_update_current_ps(struct radeon_device *rdev,
  879. struct radeon_ps *rps)
  880. {
  881. struct trinity_ps *new_ps = trinity_get_ps(rps);
  882. struct trinity_power_info *pi = trinity_get_pi(rdev);
  883. pi->current_rps = *rps;
  884. pi->current_ps = *new_ps;
  885. pi->current_rps.ps_priv = &pi->current_ps;
  886. }
  887. static void trinity_update_requested_ps(struct radeon_device *rdev,
  888. struct radeon_ps *rps)
  889. {
  890. struct trinity_ps *new_ps = trinity_get_ps(rps);
  891. struct trinity_power_info *pi = trinity_get_pi(rdev);
  892. pi->requested_rps = *rps;
  893. pi->requested_ps = *new_ps;
  894. pi->requested_rps.ps_priv = &pi->requested_ps;
  895. }
  896. void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable)
  897. {
  898. struct trinity_power_info *pi = trinity_get_pi(rdev);
  899. if (pi->enable_bapm) {
  900. trinity_acquire_mutex(rdev);
  901. trinity_dpm_bapm_enable(rdev, enable);
  902. trinity_release_mutex(rdev);
  903. }
  904. }
  905. int trinity_dpm_enable(struct radeon_device *rdev)
  906. {
  907. struct trinity_power_info *pi = trinity_get_pi(rdev);
  908. trinity_acquire_mutex(rdev);
  909. if (trinity_dpm_enabled(rdev)) {
  910. trinity_release_mutex(rdev);
  911. return -EINVAL;
  912. }
  913. trinity_program_bootup_state(rdev);
  914. sumo_program_vc(rdev, 0x00C00033);
  915. trinity_start_am(rdev);
  916. if (pi->enable_auto_thermal_throttling) {
  917. trinity_program_ttt(rdev);
  918. trinity_enable_att(rdev);
  919. }
  920. trinity_program_sclk_dpm(rdev);
  921. trinity_start_dpm(rdev);
  922. trinity_wait_for_dpm_enabled(rdev);
  923. trinity_dpm_bapm_enable(rdev, false);
  924. trinity_release_mutex(rdev);
  925. trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
  926. return 0;
  927. }
  928. int trinity_dpm_late_enable(struct radeon_device *rdev)
  929. {
  930. int ret;
  931. trinity_acquire_mutex(rdev);
  932. trinity_enable_clock_power_gating(rdev);
  933. if (rdev->irq.installed &&
  934. r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
  935. ret = trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
  936. if (ret) {
  937. trinity_release_mutex(rdev);
  938. return ret;
  939. }
  940. rdev->irq.dpm_thermal = true;
  941. radeon_irq_set(rdev);
  942. }
  943. trinity_release_mutex(rdev);
  944. return 0;
  945. }
  946. void trinity_dpm_disable(struct radeon_device *rdev)
  947. {
  948. trinity_acquire_mutex(rdev);
  949. if (!trinity_dpm_enabled(rdev)) {
  950. trinity_release_mutex(rdev);
  951. return;
  952. }
  953. trinity_dpm_bapm_enable(rdev, false);
  954. trinity_disable_clock_power_gating(rdev);
  955. sumo_clear_vc(rdev);
  956. trinity_wait_for_level_0(rdev);
  957. trinity_stop_dpm(rdev);
  958. trinity_reset_am(rdev);
  959. trinity_release_mutex(rdev);
  960. if (rdev->irq.installed &&
  961. r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
  962. rdev->irq.dpm_thermal = false;
  963. radeon_irq_set(rdev);
  964. }
  965. trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
  966. }
  967. static void trinity_get_min_sclk_divider(struct radeon_device *rdev)
  968. {
  969. struct trinity_power_info *pi = trinity_get_pi(rdev);
  970. pi->min_sclk_did =
  971. (RREG32_SMC(CC_SMU_MISC_FUSES) & MinSClkDid_MASK) >> MinSClkDid_SHIFT;
  972. }
  973. static void trinity_setup_nbp_sim(struct radeon_device *rdev,
  974. struct radeon_ps *rps)
  975. {
  976. struct trinity_power_info *pi = trinity_get_pi(rdev);
  977. struct trinity_ps *new_ps = trinity_get_ps(rps);
  978. u32 nbpsconfig;
  979. if (pi->sys_info.nb_dpm_enable) {
  980. nbpsconfig = RREG32_SMC(NB_PSTATE_CONFIG);
  981. nbpsconfig &= ~(Dpm0PgNbPsLo_MASK | Dpm0PgNbPsHi_MASK | DpmXNbPsLo_MASK | DpmXNbPsHi_MASK);
  982. nbpsconfig |= (Dpm0PgNbPsLo(new_ps->Dpm0PgNbPsLo) |
  983. Dpm0PgNbPsHi(new_ps->Dpm0PgNbPsHi) |
  984. DpmXNbPsLo(new_ps->DpmXNbPsLo) |
  985. DpmXNbPsHi(new_ps->DpmXNbPsHi));
  986. WREG32_SMC(NB_PSTATE_CONFIG, nbpsconfig);
  987. }
  988. }
  989. int trinity_dpm_force_performance_level(struct radeon_device *rdev,
  990. enum radeon_dpm_forced_level level)
  991. {
  992. struct trinity_power_info *pi = trinity_get_pi(rdev);
  993. struct radeon_ps *rps = &pi->current_rps;
  994. struct trinity_ps *ps = trinity_get_ps(rps);
  995. int i, ret;
  996. if (ps->num_levels <= 1)
  997. return 0;
  998. if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
  999. /* not supported by the hw */
  1000. return -EINVAL;
  1001. } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
  1002. ret = trinity_dpm_n_levels_disabled(rdev, ps->num_levels - 1);
  1003. if (ret)
  1004. return ret;
  1005. } else {
  1006. for (i = 0; i < ps->num_levels; i++) {
  1007. ret = trinity_dpm_n_levels_disabled(rdev, 0);
  1008. if (ret)
  1009. return ret;
  1010. }
  1011. }
  1012. rdev->pm.dpm.forced_level = level;
  1013. return 0;
  1014. }
  1015. int trinity_dpm_pre_set_power_state(struct radeon_device *rdev)
  1016. {
  1017. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1018. struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps;
  1019. struct radeon_ps *new_ps = &requested_ps;
  1020. trinity_update_requested_ps(rdev, new_ps);
  1021. trinity_apply_state_adjust_rules(rdev,
  1022. &pi->requested_rps,
  1023. &pi->current_rps);
  1024. return 0;
  1025. }
  1026. int trinity_dpm_set_power_state(struct radeon_device *rdev)
  1027. {
  1028. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1029. struct radeon_ps *new_ps = &pi->requested_rps;
  1030. struct radeon_ps *old_ps = &pi->current_rps;
  1031. trinity_acquire_mutex(rdev);
  1032. if (pi->enable_dpm) {
  1033. if (pi->enable_bapm)
  1034. trinity_dpm_bapm_enable(rdev, rdev->pm.dpm.ac_power);
  1035. trinity_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
  1036. trinity_enable_power_level_0(rdev);
  1037. trinity_force_level_0(rdev);
  1038. trinity_wait_for_level_0(rdev);
  1039. trinity_setup_nbp_sim(rdev, new_ps);
  1040. trinity_program_power_levels_0_to_n(rdev, new_ps, old_ps);
  1041. trinity_force_level_0(rdev);
  1042. trinity_unforce_levels(rdev);
  1043. trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
  1044. trinity_set_vce_clock(rdev, new_ps, old_ps);
  1045. }
  1046. trinity_release_mutex(rdev);
  1047. return 0;
  1048. }
  1049. void trinity_dpm_post_set_power_state(struct radeon_device *rdev)
  1050. {
  1051. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1052. struct radeon_ps *new_ps = &pi->requested_rps;
  1053. trinity_update_current_ps(rdev, new_ps);
  1054. }
  1055. void trinity_dpm_setup_asic(struct radeon_device *rdev)
  1056. {
  1057. trinity_acquire_mutex(rdev);
  1058. sumo_program_sstp(rdev);
  1059. sumo_take_smu_control(rdev, true);
  1060. trinity_get_min_sclk_divider(rdev);
  1061. trinity_release_mutex(rdev);
  1062. }
  1063. #if 0
  1064. void trinity_dpm_reset_asic(struct radeon_device *rdev)
  1065. {
  1066. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1067. trinity_acquire_mutex(rdev);
  1068. if (pi->enable_dpm) {
  1069. trinity_enable_power_level_0(rdev);
  1070. trinity_force_level_0(rdev);
  1071. trinity_wait_for_level_0(rdev);
  1072. trinity_program_bootup_state(rdev);
  1073. trinity_force_level_0(rdev);
  1074. trinity_unforce_levels(rdev);
  1075. }
  1076. trinity_release_mutex(rdev);
  1077. }
  1078. #endif
  1079. static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev,
  1080. u32 vid_2bit)
  1081. {
  1082. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1083. u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit);
  1084. u32 svi_mode = (RREG32_SMC(PM_CONFIG) & SVI_Mode) ? 1 : 0;
  1085. u32 step = (svi_mode == 0) ? 1250 : 625;
  1086. u32 delta = vid_7bit * step + 50;
  1087. if (delta > 155000)
  1088. return 0;
  1089. return (155000 - delta) / 100;
  1090. }
  1091. static void trinity_patch_boot_state(struct radeon_device *rdev,
  1092. struct trinity_ps *ps)
  1093. {
  1094. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1095. ps->num_levels = 1;
  1096. ps->nbps_flags = 0;
  1097. ps->bapm_flags = 0;
  1098. ps->levels[0] = pi->boot_pl;
  1099. }
  1100. static u8 trinity_calculate_vce_wm(struct radeon_device *rdev, u32 sclk)
  1101. {
  1102. if (sclk < 20000)
  1103. return 1;
  1104. return 0;
  1105. }
  1106. static void trinity_construct_boot_state(struct radeon_device *rdev)
  1107. {
  1108. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1109. pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
  1110. pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
  1111. pi->boot_pl.ds_divider_index = 0;
  1112. pi->boot_pl.ss_divider_index = 0;
  1113. pi->boot_pl.allow_gnb_slow = 1;
  1114. pi->boot_pl.force_nbp_state = 0;
  1115. pi->boot_pl.display_wm = 0;
  1116. pi->boot_pl.vce_wm = 0;
  1117. pi->current_ps.num_levels = 1;
  1118. pi->current_ps.levels[0] = pi->boot_pl;
  1119. }
  1120. static u8 trinity_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
  1121. u32 sclk, u32 min_sclk_in_sr)
  1122. {
  1123. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1124. u32 i;
  1125. u32 temp;
  1126. u32 min = (min_sclk_in_sr > TRINITY_MINIMUM_ENGINE_CLOCK) ?
  1127. min_sclk_in_sr : TRINITY_MINIMUM_ENGINE_CLOCK;
  1128. if (sclk < min)
  1129. return 0;
  1130. if (!pi->enable_sclk_ds)
  1131. return 0;
  1132. for (i = TRINITY_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) {
  1133. temp = sclk / sumo_get_sleep_divider_from_id(i);
  1134. if (temp >= min || i == 0)
  1135. break;
  1136. }
  1137. return (u8)i;
  1138. }
  1139. static u32 trinity_get_valid_engine_clock(struct radeon_device *rdev,
  1140. u32 lower_limit)
  1141. {
  1142. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1143. u32 i;
  1144. for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) {
  1145. if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit)
  1146. return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency;
  1147. }
  1148. if (i == pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries)
  1149. DRM_ERROR("engine clock out of range!");
  1150. return 0;
  1151. }
  1152. static void trinity_patch_thermal_state(struct radeon_device *rdev,
  1153. struct trinity_ps *ps,
  1154. struct trinity_ps *current_ps)
  1155. {
  1156. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1157. u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
  1158. u32 current_vddc;
  1159. u32 current_sclk;
  1160. u32 current_index = 0;
  1161. if (current_ps) {
  1162. current_vddc = current_ps->levels[current_index].vddc_index;
  1163. current_sclk = current_ps->levels[current_index].sclk;
  1164. } else {
  1165. current_vddc = pi->boot_pl.vddc_index;
  1166. current_sclk = pi->boot_pl.sclk;
  1167. }
  1168. ps->levels[0].vddc_index = current_vddc;
  1169. if (ps->levels[0].sclk > current_sclk)
  1170. ps->levels[0].sclk = current_sclk;
  1171. ps->levels[0].ds_divider_index =
  1172. trinity_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr);
  1173. ps->levels[0].ss_divider_index = ps->levels[0].ds_divider_index;
  1174. ps->levels[0].allow_gnb_slow = 1;
  1175. ps->levels[0].force_nbp_state = 0;
  1176. ps->levels[0].display_wm = 0;
  1177. ps->levels[0].vce_wm =
  1178. trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
  1179. }
  1180. static u8 trinity_calculate_display_wm(struct radeon_device *rdev,
  1181. struct trinity_ps *ps, u32 index)
  1182. {
  1183. if (ps == NULL || ps->num_levels <= 1)
  1184. return 0;
  1185. else if (ps->num_levels == 2) {
  1186. if (index == 0)
  1187. return 0;
  1188. else
  1189. return 1;
  1190. } else {
  1191. if (index == 0)
  1192. return 0;
  1193. else if (ps->levels[index].sclk < 30000)
  1194. return 0;
  1195. else
  1196. return 1;
  1197. }
  1198. }
  1199. static u32 trinity_get_uvd_clock_index(struct radeon_device *rdev,
  1200. struct radeon_ps *rps)
  1201. {
  1202. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1203. u32 i = 0;
  1204. for (i = 0; i < 4; i++) {
  1205. if ((rps->vclk == pi->sys_info.uvd_clock_table_entries[i].vclk) &&
  1206. (rps->dclk == pi->sys_info.uvd_clock_table_entries[i].dclk))
  1207. break;
  1208. }
  1209. if (i >= 4) {
  1210. DRM_ERROR("UVD clock index not found!\n");
  1211. i = 3;
  1212. }
  1213. return i;
  1214. }
  1215. static void trinity_adjust_uvd_state(struct radeon_device *rdev,
  1216. struct radeon_ps *rps)
  1217. {
  1218. struct trinity_ps *ps = trinity_get_ps(rps);
  1219. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1220. u32 high_index = 0;
  1221. u32 low_index = 0;
  1222. if (pi->uvd_dpm && r600_is_uvd_state(rps->class, rps->class2)) {
  1223. high_index = trinity_get_uvd_clock_index(rdev, rps);
  1224. switch(high_index) {
  1225. case 3:
  1226. case 2:
  1227. low_index = 1;
  1228. break;
  1229. case 1:
  1230. case 0:
  1231. default:
  1232. low_index = 0;
  1233. break;
  1234. }
  1235. ps->vclk_low_divider =
  1236. pi->sys_info.uvd_clock_table_entries[high_index].vclk_did;
  1237. ps->dclk_low_divider =
  1238. pi->sys_info.uvd_clock_table_entries[high_index].dclk_did;
  1239. ps->vclk_high_divider =
  1240. pi->sys_info.uvd_clock_table_entries[low_index].vclk_did;
  1241. ps->dclk_high_divider =
  1242. pi->sys_info.uvd_clock_table_entries[low_index].dclk_did;
  1243. }
  1244. }
  1245. static int trinity_get_vce_clock_voltage(struct radeon_device *rdev,
  1246. u32 evclk, u32 ecclk, u16 *voltage)
  1247. {
  1248. u32 i;
  1249. int ret = -EINVAL;
  1250. struct radeon_vce_clock_voltage_dependency_table *table =
  1251. &rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
  1252. if (((evclk == 0) && (ecclk == 0)) ||
  1253. (table && (table->count == 0))) {
  1254. *voltage = 0;
  1255. return 0;
  1256. }
  1257. for (i = 0; i < table->count; i++) {
  1258. if ((evclk <= table->entries[i].evclk) &&
  1259. (ecclk <= table->entries[i].ecclk)) {
  1260. *voltage = table->entries[i].v;
  1261. ret = 0;
  1262. break;
  1263. }
  1264. }
  1265. /* if no match return the highest voltage */
  1266. if (ret)
  1267. *voltage = table->entries[table->count - 1].v;
  1268. return ret;
  1269. }
  1270. static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
  1271. struct radeon_ps *new_rps,
  1272. struct radeon_ps *old_rps)
  1273. {
  1274. struct trinity_ps *ps = trinity_get_ps(new_rps);
  1275. struct trinity_ps *current_ps = trinity_get_ps(old_rps);
  1276. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1277. u32 min_voltage = 0; /* ??? */
  1278. u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
  1279. u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
  1280. u32 i;
  1281. u16 min_vce_voltage;
  1282. bool force_high;
  1283. u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
  1284. if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
  1285. return trinity_patch_thermal_state(rdev, ps, current_ps);
  1286. trinity_adjust_uvd_state(rdev, new_rps);
  1287. if (new_rps->vce_active) {
  1288. new_rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
  1289. new_rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
  1290. } else {
  1291. new_rps->evclk = 0;
  1292. new_rps->ecclk = 0;
  1293. }
  1294. for (i = 0; i < ps->num_levels; i++) {
  1295. if (ps->levels[i].vddc_index < min_voltage)
  1296. ps->levels[i].vddc_index = min_voltage;
  1297. if (ps->levels[i].sclk < min_sclk)
  1298. ps->levels[i].sclk =
  1299. trinity_get_valid_engine_clock(rdev, min_sclk);
  1300. /* patch in vce limits */
  1301. if (new_rps->vce_active) {
  1302. /* sclk */
  1303. if (ps->levels[i].sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
  1304. ps->levels[i].sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
  1305. /* vddc */
  1306. trinity_get_vce_clock_voltage(rdev, new_rps->evclk, new_rps->ecclk, &min_vce_voltage);
  1307. if (ps->levels[i].vddc_index < min_vce_voltage)
  1308. ps->levels[i].vddc_index = min_vce_voltage;
  1309. }
  1310. ps->levels[i].ds_divider_index =
  1311. sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
  1312. ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index;
  1313. ps->levels[i].allow_gnb_slow = 1;
  1314. ps->levels[i].force_nbp_state = 0;
  1315. ps->levels[i].display_wm =
  1316. trinity_calculate_display_wm(rdev, ps, i);
  1317. ps->levels[i].vce_wm =
  1318. trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
  1319. }
  1320. if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
  1321. ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY))
  1322. ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE;
  1323. if (pi->sys_info.nb_dpm_enable) {
  1324. ps->Dpm0PgNbPsLo = 0x1;
  1325. ps->Dpm0PgNbPsHi = 0x0;
  1326. ps->DpmXNbPsLo = 0x2;
  1327. ps->DpmXNbPsHi = 0x1;
  1328. if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
  1329. ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) {
  1330. force_high = ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) ||
  1331. ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) &&
  1332. (pi->sys_info.uma_channel_number == 1)));
  1333. force_high = (num_active_displays >= 3) || force_high;
  1334. ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3;
  1335. ps->Dpm0PgNbPsHi = 0x1;
  1336. ps->DpmXNbPsLo = force_high ? 0x2 : 0x3;
  1337. ps->DpmXNbPsHi = 0x2;
  1338. ps->levels[ps->num_levels - 1].allow_gnb_slow = 0;
  1339. }
  1340. }
  1341. }
  1342. static void trinity_cleanup_asic(struct radeon_device *rdev)
  1343. {
  1344. sumo_take_smu_control(rdev, false);
  1345. }
  1346. #if 0
  1347. static void trinity_pre_display_configuration_change(struct radeon_device *rdev)
  1348. {
  1349. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1350. if (pi->voltage_drop_in_dce)
  1351. trinity_dce_enable_voltage_adjustment(rdev, false);
  1352. }
  1353. #endif
  1354. static void trinity_add_dccac_value(struct radeon_device *rdev)
  1355. {
  1356. u32 gpu_cac_avrg_cntl_window_size;
  1357. u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
  1358. u64 disp_clk = rdev->clock.default_dispclk / 100;
  1359. u32 dc_cac_value;
  1360. gpu_cac_avrg_cntl_window_size =
  1361. (RREG32_SMC(GPU_CAC_AVRG_CNTL) & WINDOW_SIZE_MASK) >> WINDOW_SIZE_SHIFT;
  1362. dc_cac_value = (u32)((14213 * disp_clk * disp_clk * (u64)num_active_displays) >>
  1363. (32 - gpu_cac_avrg_cntl_window_size));
  1364. WREG32_SMC(DC_CAC_VALUE, dc_cac_value);
  1365. }
  1366. void trinity_dpm_display_configuration_changed(struct radeon_device *rdev)
  1367. {
  1368. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1369. if (pi->voltage_drop_in_dce)
  1370. trinity_dce_enable_voltage_adjustment(rdev, true);
  1371. trinity_add_dccac_value(rdev);
  1372. }
  1373. union power_info {
  1374. struct _ATOM_POWERPLAY_INFO info;
  1375. struct _ATOM_POWERPLAY_INFO_V2 info_2;
  1376. struct _ATOM_POWERPLAY_INFO_V3 info_3;
  1377. struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
  1378. struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
  1379. struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
  1380. };
  1381. union pplib_clock_info {
  1382. struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
  1383. struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
  1384. struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
  1385. struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
  1386. };
  1387. union pplib_power_state {
  1388. struct _ATOM_PPLIB_STATE v1;
  1389. struct _ATOM_PPLIB_STATE_V2 v2;
  1390. };
  1391. static void trinity_parse_pplib_non_clock_info(struct radeon_device *rdev,
  1392. struct radeon_ps *rps,
  1393. struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
  1394. u8 table_rev)
  1395. {
  1396. struct trinity_ps *ps = trinity_get_ps(rps);
  1397. rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
  1398. rps->class = le16_to_cpu(non_clock_info->usClassification);
  1399. rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
  1400. if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
  1401. rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
  1402. rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
  1403. } else {
  1404. rps->vclk = 0;
  1405. rps->dclk = 0;
  1406. }
  1407. if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
  1408. rdev->pm.dpm.boot_ps = rps;
  1409. trinity_patch_boot_state(rdev, ps);
  1410. }
  1411. if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
  1412. rdev->pm.dpm.uvd_ps = rps;
  1413. }
  1414. static void trinity_parse_pplib_clock_info(struct radeon_device *rdev,
  1415. struct radeon_ps *rps, int index,
  1416. union pplib_clock_info *clock_info)
  1417. {
  1418. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1419. struct trinity_ps *ps = trinity_get_ps(rps);
  1420. struct trinity_pl *pl = &ps->levels[index];
  1421. u32 sclk;
  1422. sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
  1423. sclk |= clock_info->sumo.ucEngineClockHigh << 16;
  1424. pl->sclk = sclk;
  1425. pl->vddc_index = clock_info->sumo.vddcIndex;
  1426. ps->num_levels = index + 1;
  1427. if (pi->enable_sclk_ds) {
  1428. pl->ds_divider_index = 5;
  1429. pl->ss_divider_index = 5;
  1430. }
  1431. }
  1432. static int trinity_parse_power_table(struct radeon_device *rdev)
  1433. {
  1434. struct radeon_mode_info *mode_info = &rdev->mode_info;
  1435. struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
  1436. union pplib_power_state *power_state;
  1437. int i, j, k, non_clock_array_index, clock_array_index;
  1438. union pplib_clock_info *clock_info;
  1439. struct _StateArray *state_array;
  1440. struct _ClockInfoArray *clock_info_array;
  1441. struct _NonClockInfoArray *non_clock_info_array;
  1442. union power_info *power_info;
  1443. int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
  1444. u16 data_offset;
  1445. u8 frev, crev;
  1446. u8 *power_state_offset;
  1447. struct sumo_ps *ps;
  1448. if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
  1449. &frev, &crev, &data_offset))
  1450. return -EINVAL;
  1451. power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
  1452. state_array = (struct _StateArray *)
  1453. (mode_info->atom_context->bios + data_offset +
  1454. le16_to_cpu(power_info->pplib.usStateArrayOffset));
  1455. clock_info_array = (struct _ClockInfoArray *)
  1456. (mode_info->atom_context->bios + data_offset +
  1457. le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
  1458. non_clock_info_array = (struct _NonClockInfoArray *)
  1459. (mode_info->atom_context->bios + data_offset +
  1460. le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
  1461. rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
  1462. sizeof(struct radeon_ps),
  1463. GFP_KERNEL);
  1464. if (!rdev->pm.dpm.ps)
  1465. return -ENOMEM;
  1466. power_state_offset = (u8 *)state_array->states;
  1467. for (i = 0; i < state_array->ucNumEntries; i++) {
  1468. u8 *idx;
  1469. power_state = (union pplib_power_state *)power_state_offset;
  1470. non_clock_array_index = power_state->v2.nonClockInfoIndex;
  1471. non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
  1472. &non_clock_info_array->nonClockInfo[non_clock_array_index];
  1473. if (!rdev->pm.power_state[i].clock_info)
  1474. return -EINVAL;
  1475. ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
  1476. if (ps == NULL) {
  1477. kfree(rdev->pm.dpm.ps);
  1478. return -ENOMEM;
  1479. }
  1480. rdev->pm.dpm.ps[i].ps_priv = ps;
  1481. k = 0;
  1482. idx = (u8 *)&power_state->v2.clockInfoIndex[0];
  1483. for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
  1484. clock_array_index = idx[j];
  1485. if (clock_array_index >= clock_info_array->ucNumEntries)
  1486. continue;
  1487. if (k >= SUMO_MAX_HARDWARE_POWERLEVELS)
  1488. break;
  1489. clock_info = (union pplib_clock_info *)
  1490. ((u8 *)&clock_info_array->clockInfo[0] +
  1491. (clock_array_index * clock_info_array->ucEntrySize));
  1492. trinity_parse_pplib_clock_info(rdev,
  1493. &rdev->pm.dpm.ps[i], k,
  1494. clock_info);
  1495. k++;
  1496. }
  1497. trinity_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
  1498. non_clock_info,
  1499. non_clock_info_array->ucEntrySize);
  1500. power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
  1501. }
  1502. rdev->pm.dpm.num_ps = state_array->ucNumEntries;
  1503. /* fill in the vce power states */
  1504. for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
  1505. u32 sclk;
  1506. clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
  1507. clock_info = (union pplib_clock_info *)
  1508. &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
  1509. sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
  1510. sclk |= clock_info->sumo.ucEngineClockHigh << 16;
  1511. rdev->pm.dpm.vce_states[i].sclk = sclk;
  1512. rdev->pm.dpm.vce_states[i].mclk = 0;
  1513. }
  1514. return 0;
  1515. }
  1516. union igp_info {
  1517. struct _ATOM_INTEGRATED_SYSTEM_INFO info;
  1518. struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
  1519. struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5;
  1520. struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
  1521. struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
  1522. };
  1523. static u32 trinity_convert_did_to_freq(struct radeon_device *rdev, u8 did)
  1524. {
  1525. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1526. u32 divider;
  1527. if (did >= 8 && did <= 0x3f)
  1528. divider = did * 25;
  1529. else if (did > 0x3f && did <= 0x5f)
  1530. divider = (did - 64) * 50 + 1600;
  1531. else if (did > 0x5f && did <= 0x7e)
  1532. divider = (did - 96) * 100 + 3200;
  1533. else if (did == 0x7f)
  1534. divider = 128 * 100;
  1535. else
  1536. return 10000;
  1537. return ((pi->sys_info.dentist_vco_freq * 100) + (divider - 1)) / divider;
  1538. }
  1539. static int trinity_parse_sys_info_table(struct radeon_device *rdev)
  1540. {
  1541. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1542. struct radeon_mode_info *mode_info = &rdev->mode_info;
  1543. int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
  1544. union igp_info *igp_info;
  1545. u8 frev, crev;
  1546. u16 data_offset;
  1547. int i;
  1548. if (atom_parse_data_header(mode_info->atom_context, index, NULL,
  1549. &frev, &crev, &data_offset)) {
  1550. igp_info = (union igp_info *)(mode_info->atom_context->bios +
  1551. data_offset);
  1552. if (crev != 7) {
  1553. DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
  1554. return -EINVAL;
  1555. }
  1556. pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_7.ulBootUpEngineClock);
  1557. pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_7.ulMinEngineClock);
  1558. pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_7.ulBootUpUMAClock);
  1559. pi->sys_info.dentist_vco_freq = le32_to_cpu(igp_info->info_7.ulDentistVCOFreq);
  1560. pi->sys_info.bootup_nb_voltage_index =
  1561. le16_to_cpu(igp_info->info_7.usBootUpNBVoltage);
  1562. if (igp_info->info_7.ucHtcTmpLmt == 0)
  1563. pi->sys_info.htc_tmp_lmt = 203;
  1564. else
  1565. pi->sys_info.htc_tmp_lmt = igp_info->info_7.ucHtcTmpLmt;
  1566. if (igp_info->info_7.ucHtcHystLmt == 0)
  1567. pi->sys_info.htc_hyst_lmt = 5;
  1568. else
  1569. pi->sys_info.htc_hyst_lmt = igp_info->info_7.ucHtcHystLmt;
  1570. if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
  1571. DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n");
  1572. }
  1573. if (pi->enable_nbps_policy)
  1574. pi->sys_info.nb_dpm_enable = igp_info->info_7.ucNBDPMEnable;
  1575. else
  1576. pi->sys_info.nb_dpm_enable = 0;
  1577. for (i = 0; i < TRINITY_NUM_NBPSTATES; i++) {
  1578. pi->sys_info.nbp_mclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateMemclkFreq[i]);
  1579. pi->sys_info.nbp_nclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateNClkFreq[i]);
  1580. }
  1581. pi->sys_info.nbp_voltage_index[0] = le16_to_cpu(igp_info->info_7.usNBP0Voltage);
  1582. pi->sys_info.nbp_voltage_index[1] = le16_to_cpu(igp_info->info_7.usNBP1Voltage);
  1583. pi->sys_info.nbp_voltage_index[2] = le16_to_cpu(igp_info->info_7.usNBP2Voltage);
  1584. pi->sys_info.nbp_voltage_index[3] = le16_to_cpu(igp_info->info_7.usNBP3Voltage);
  1585. if (!pi->sys_info.nb_dpm_enable) {
  1586. for (i = 1; i < TRINITY_NUM_NBPSTATES; i++) {
  1587. pi->sys_info.nbp_mclk[i] = pi->sys_info.nbp_mclk[0];
  1588. pi->sys_info.nbp_nclk[i] = pi->sys_info.nbp_nclk[0];
  1589. pi->sys_info.nbp_voltage_index[i] = pi->sys_info.nbp_voltage_index[0];
  1590. }
  1591. }
  1592. pi->sys_info.uma_channel_number = igp_info->info_7.ucUMAChannelNumber;
  1593. sumo_construct_sclk_voltage_mapping_table(rdev,
  1594. &pi->sys_info.sclk_voltage_mapping_table,
  1595. igp_info->info_7.sAvail_SCLK);
  1596. sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table,
  1597. igp_info->info_7.sAvail_SCLK);
  1598. pi->sys_info.uvd_clock_table_entries[0].vclk_did =
  1599. igp_info->info_7.ucDPMState0VclkFid;
  1600. pi->sys_info.uvd_clock_table_entries[1].vclk_did =
  1601. igp_info->info_7.ucDPMState1VclkFid;
  1602. pi->sys_info.uvd_clock_table_entries[2].vclk_did =
  1603. igp_info->info_7.ucDPMState2VclkFid;
  1604. pi->sys_info.uvd_clock_table_entries[3].vclk_did =
  1605. igp_info->info_7.ucDPMState3VclkFid;
  1606. pi->sys_info.uvd_clock_table_entries[0].dclk_did =
  1607. igp_info->info_7.ucDPMState0DclkFid;
  1608. pi->sys_info.uvd_clock_table_entries[1].dclk_did =
  1609. igp_info->info_7.ucDPMState1DclkFid;
  1610. pi->sys_info.uvd_clock_table_entries[2].dclk_did =
  1611. igp_info->info_7.ucDPMState2DclkFid;
  1612. pi->sys_info.uvd_clock_table_entries[3].dclk_did =
  1613. igp_info->info_7.ucDPMState3DclkFid;
  1614. for (i = 0; i < 4; i++) {
  1615. pi->sys_info.uvd_clock_table_entries[i].vclk =
  1616. trinity_convert_did_to_freq(rdev,
  1617. pi->sys_info.uvd_clock_table_entries[i].vclk_did);
  1618. pi->sys_info.uvd_clock_table_entries[i].dclk =
  1619. trinity_convert_did_to_freq(rdev,
  1620. pi->sys_info.uvd_clock_table_entries[i].dclk_did);
  1621. }
  1622. }
  1623. return 0;
  1624. }
  1625. int trinity_dpm_init(struct radeon_device *rdev)
  1626. {
  1627. struct trinity_power_info *pi;
  1628. int ret, i;
  1629. pi = kzalloc(sizeof(struct trinity_power_info), GFP_KERNEL);
  1630. if (pi == NULL)
  1631. return -ENOMEM;
  1632. rdev->pm.dpm.priv = pi;
  1633. for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++)
  1634. pi->at[i] = TRINITY_AT_DFLT;
  1635. if (radeon_bapm == -1) {
  1636. /* There are stability issues reported on with
  1637. * bapm enabled when switching between AC and battery
  1638. * power. At the same time, some MSI boards hang
  1639. * if it's not enabled and dpm is enabled. Just enable
  1640. * it for MSI boards right now.
  1641. */
  1642. if (rdev->pdev->subsystem_vendor == 0x1462)
  1643. pi->enable_bapm = true;
  1644. else
  1645. pi->enable_bapm = false;
  1646. } else if (radeon_bapm == 0) {
  1647. pi->enable_bapm = false;
  1648. } else {
  1649. pi->enable_bapm = true;
  1650. }
  1651. pi->enable_nbps_policy = true;
  1652. pi->enable_sclk_ds = true;
  1653. pi->enable_gfx_power_gating = true;
  1654. pi->enable_gfx_clock_gating = true;
  1655. pi->enable_mg_clock_gating = false;
  1656. pi->enable_gfx_dynamic_mgpg = false;
  1657. pi->override_dynamic_mgpg = false;
  1658. pi->enable_auto_thermal_throttling = true;
  1659. pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */
  1660. pi->uvd_dpm = true; /* ??? */
  1661. ret = trinity_parse_sys_info_table(rdev);
  1662. if (ret)
  1663. return ret;
  1664. trinity_construct_boot_state(rdev);
  1665. ret = r600_get_platform_caps(rdev);
  1666. if (ret)
  1667. return ret;
  1668. ret = r600_parse_extended_power_table(rdev);
  1669. if (ret)
  1670. return ret;
  1671. ret = trinity_parse_power_table(rdev);
  1672. if (ret)
  1673. return ret;
  1674. pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt;
  1675. pi->enable_dpm = true;
  1676. return 0;
  1677. }
  1678. void trinity_dpm_print_power_state(struct radeon_device *rdev,
  1679. struct radeon_ps *rps)
  1680. {
  1681. int i;
  1682. struct trinity_ps *ps = trinity_get_ps(rps);
  1683. r600_dpm_print_class_info(rps->class, rps->class2);
  1684. r600_dpm_print_cap_info(rps->caps);
  1685. printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
  1686. for (i = 0; i < ps->num_levels; i++) {
  1687. struct trinity_pl *pl = &ps->levels[i];
  1688. printk("\t\tpower level %d sclk: %u vddc: %u\n",
  1689. i, pl->sclk,
  1690. trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
  1691. }
  1692. r600_dpm_print_ps_status(rdev, rps);
  1693. }
  1694. void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
  1695. struct seq_file *m)
  1696. {
  1697. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1698. struct radeon_ps *rps = &pi->current_rps;
  1699. struct trinity_ps *ps = trinity_get_ps(rps);
  1700. struct trinity_pl *pl;
  1701. u32 current_index =
  1702. (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >>
  1703. CURRENT_STATE_SHIFT;
  1704. if (current_index >= ps->num_levels) {
  1705. seq_printf(m, "invalid dpm profile %d\n", current_index);
  1706. } else {
  1707. pl = &ps->levels[current_index];
  1708. seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
  1709. seq_printf(m, "power level %d sclk: %u vddc: %u\n",
  1710. current_index, pl->sclk,
  1711. trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
  1712. }
  1713. }
  1714. u32 trinity_dpm_get_current_sclk(struct radeon_device *rdev)
  1715. {
  1716. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1717. struct radeon_ps *rps = &pi->current_rps;
  1718. struct trinity_ps *ps = trinity_get_ps(rps);
  1719. struct trinity_pl *pl;
  1720. u32 current_index =
  1721. (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >>
  1722. CURRENT_STATE_SHIFT;
  1723. if (current_index >= ps->num_levels) {
  1724. return 0;
  1725. } else {
  1726. pl = &ps->levels[current_index];
  1727. return pl->sclk;
  1728. }
  1729. }
  1730. u32 trinity_dpm_get_current_mclk(struct radeon_device *rdev)
  1731. {
  1732. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1733. return pi->sys_info.bootup_uma_clk;
  1734. }
  1735. void trinity_dpm_fini(struct radeon_device *rdev)
  1736. {
  1737. int i;
  1738. trinity_cleanup_asic(rdev); /* ??? */
  1739. for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
  1740. kfree(rdev->pm.dpm.ps[i].ps_priv);
  1741. }
  1742. kfree(rdev->pm.dpm.ps);
  1743. kfree(rdev->pm.dpm.priv);
  1744. r600_free_extended_power_table(rdev);
  1745. }
  1746. u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)
  1747. {
  1748. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1749. struct trinity_ps *requested_state = trinity_get_ps(&pi->requested_rps);
  1750. if (low)
  1751. return requested_state->levels[0].sclk;
  1752. else
  1753. return requested_state->levels[requested_state->num_levels - 1].sclk;
  1754. }
  1755. u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low)
  1756. {
  1757. struct trinity_power_info *pi = trinity_get_pi(rdev);
  1758. return pi->sys_info.bootup_uma_clk;
  1759. }