processpptables.c 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730
  1. /*
  2. * Copyright 2015 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 "pp_debug.h"
  24. #include <linux/types.h>
  25. #include <linux/kernel.h>
  26. #include <linux/slab.h>
  27. #include <drm/amdgpu_drm.h>
  28. #include "processpptables.h"
  29. #include <atom-types.h>
  30. #include <atombios.h>
  31. #include "pptable.h"
  32. #include "power_state.h"
  33. #include "hwmgr.h"
  34. #include "hardwaremanager.h"
  35. #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
  36. #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
  37. #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
  38. #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
  39. #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
  40. #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
  41. #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24
  42. #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26
  43. #define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6
  44. static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr,
  45. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  46. {
  47. uint16_t vce_table_offset = 0;
  48. if (le16_to_cpu(powerplay_table->usTableSize) >=
  49. sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
  50. const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
  51. (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
  52. if (powerplay_table3->usExtendendedHeaderOffset > 0) {
  53. const ATOM_PPLIB_EXTENDEDHEADER *extended_header =
  54. (const ATOM_PPLIB_EXTENDEDHEADER *)
  55. (((unsigned long)powerplay_table3) +
  56. le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
  57. if (le16_to_cpu(extended_header->usSize) >=
  58. SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2)
  59. vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset);
  60. }
  61. }
  62. return vce_table_offset;
  63. }
  64. static uint16_t get_vce_clock_info_array_offset(struct pp_hwmgr *hwmgr,
  65. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  66. {
  67. uint16_t table_offset = get_vce_table_offset(hwmgr,
  68. powerplay_table);
  69. if (table_offset > 0)
  70. return table_offset + 1;
  71. return 0;
  72. }
  73. static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr *hwmgr,
  74. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  75. {
  76. uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,
  77. powerplay_table);
  78. uint16_t table_size = 0;
  79. if (table_offset > 0) {
  80. const VCEClockInfoArray *p = (const VCEClockInfoArray *)
  81. (((unsigned long) powerplay_table) + table_offset);
  82. table_size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo);
  83. }
  84. return table_size;
  85. }
  86. static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr *hwmgr,
  87. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  88. {
  89. uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,
  90. powerplay_table);
  91. if (table_offset > 0)
  92. return table_offset + get_vce_clock_info_array_size(hwmgr,
  93. powerplay_table);
  94. return 0;
  95. }
  96. static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr,
  97. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  98. {
  99. uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
  100. uint16_t table_size = 0;
  101. if (table_offset > 0) {
  102. const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *ptable =
  103. (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)(((unsigned long) powerplay_table) + table_offset);
  104. table_size = sizeof(uint8_t) + ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record);
  105. }
  106. return table_size;
  107. }
  108. static uint16_t get_vce_state_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  109. {
  110. uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
  111. if (table_offset > 0)
  112. return table_offset + get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table);
  113. return 0;
  114. }
  115. static const ATOM_PPLIB_VCE_State_Table *get_vce_state_table(
  116. struct pp_hwmgr *hwmgr,
  117. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  118. {
  119. uint16_t table_offset = get_vce_state_table_offset(hwmgr, powerplay_table);
  120. if (table_offset > 0)
  121. return (const ATOM_PPLIB_VCE_State_Table *)(((unsigned long) powerplay_table) + table_offset);
  122. return NULL;
  123. }
  124. static uint16_t get_uvd_table_offset(struct pp_hwmgr *hwmgr,
  125. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  126. {
  127. uint16_t uvd_table_offset = 0;
  128. if (le16_to_cpu(powerplay_table->usTableSize) >=
  129. sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
  130. const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
  131. (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
  132. if (powerplay_table3->usExtendendedHeaderOffset > 0) {
  133. const ATOM_PPLIB_EXTENDEDHEADER *extended_header =
  134. (const ATOM_PPLIB_EXTENDEDHEADER *)
  135. (((unsigned long)powerplay_table3) +
  136. le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
  137. if (le16_to_cpu(extended_header->usSize) >=
  138. SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3)
  139. uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset);
  140. }
  141. }
  142. return uvd_table_offset;
  143. }
  144. static uint16_t get_uvd_clock_info_array_offset(struct pp_hwmgr *hwmgr,
  145. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  146. {
  147. uint16_t table_offset = get_uvd_table_offset(hwmgr,
  148. powerplay_table);
  149. if (table_offset > 0)
  150. return table_offset + 1;
  151. return 0;
  152. }
  153. static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr *hwmgr,
  154. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  155. {
  156. uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,
  157. powerplay_table);
  158. uint16_t table_size = 0;
  159. if (table_offset > 0) {
  160. const UVDClockInfoArray *p = (const UVDClockInfoArray *)
  161. (((unsigned long) powerplay_table)
  162. + table_offset);
  163. table_size = sizeof(UCHAR) +
  164. p->ucNumEntries * sizeof(UVDClockInfo);
  165. }
  166. return table_size;
  167. }
  168. static uint16_t get_uvd_clock_voltage_limit_table_offset(
  169. struct pp_hwmgr *hwmgr,
  170. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  171. {
  172. uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,
  173. powerplay_table);
  174. if (table_offset > 0)
  175. return table_offset +
  176. get_uvd_clock_info_array_size(hwmgr, powerplay_table);
  177. return 0;
  178. }
  179. static uint16_t get_samu_table_offset(struct pp_hwmgr *hwmgr,
  180. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  181. {
  182. uint16_t samu_table_offset = 0;
  183. if (le16_to_cpu(powerplay_table->usTableSize) >=
  184. sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
  185. const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
  186. (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
  187. if (powerplay_table3->usExtendendedHeaderOffset > 0) {
  188. const ATOM_PPLIB_EXTENDEDHEADER *extended_header =
  189. (const ATOM_PPLIB_EXTENDEDHEADER *)
  190. (((unsigned long)powerplay_table3) +
  191. le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
  192. if (le16_to_cpu(extended_header->usSize) >=
  193. SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4)
  194. samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset);
  195. }
  196. }
  197. return samu_table_offset;
  198. }
  199. static uint16_t get_samu_clock_voltage_limit_table_offset(
  200. struct pp_hwmgr *hwmgr,
  201. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  202. {
  203. uint16_t table_offset = get_samu_table_offset(hwmgr,
  204. powerplay_table);
  205. if (table_offset > 0)
  206. return table_offset + 1;
  207. return 0;
  208. }
  209. static uint16_t get_acp_table_offset(struct pp_hwmgr *hwmgr,
  210. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  211. {
  212. uint16_t acp_table_offset = 0;
  213. if (le16_to_cpu(powerplay_table->usTableSize) >=
  214. sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
  215. const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
  216. (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
  217. if (powerplay_table3->usExtendendedHeaderOffset > 0) {
  218. const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =
  219. (const ATOM_PPLIB_EXTENDEDHEADER *)
  220. (((unsigned long)powerplay_table3) +
  221. le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
  222. if (le16_to_cpu(pExtendedHeader->usSize) >=
  223. SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6)
  224. acp_table_offset = le16_to_cpu(pExtendedHeader->usACPTableOffset);
  225. }
  226. }
  227. return acp_table_offset;
  228. }
  229. static uint16_t get_acp_clock_voltage_limit_table_offset(
  230. struct pp_hwmgr *hwmgr,
  231. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  232. {
  233. uint16_t tableOffset = get_acp_table_offset(hwmgr, powerplay_table);
  234. if (tableOffset > 0)
  235. return tableOffset + 1;
  236. return 0;
  237. }
  238. static uint16_t get_cacp_tdp_table_offset(
  239. struct pp_hwmgr *hwmgr,
  240. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  241. {
  242. uint16_t cacTdpTableOffset = 0;
  243. if (le16_to_cpu(powerplay_table->usTableSize) >=
  244. sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
  245. const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
  246. (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
  247. if (powerplay_table3->usExtendendedHeaderOffset > 0) {
  248. const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =
  249. (const ATOM_PPLIB_EXTENDEDHEADER *)
  250. (((unsigned long)powerplay_table3) +
  251. le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
  252. if (le16_to_cpu(pExtendedHeader->usSize) >=
  253. SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7)
  254. cacTdpTableOffset = le16_to_cpu(pExtendedHeader->usPowerTuneTableOffset);
  255. }
  256. }
  257. return cacTdpTableOffset;
  258. }
  259. static int get_cac_tdp_table(struct pp_hwmgr *hwmgr,
  260. struct phm_cac_tdp_table **ptable,
  261. const ATOM_PowerTune_Table *table,
  262. uint16_t us_maximum_power_delivery_limit)
  263. {
  264. unsigned long table_size;
  265. struct phm_cac_tdp_table *tdp_table;
  266. table_size = sizeof(unsigned long) + sizeof(struct phm_cac_tdp_table);
  267. tdp_table = kzalloc(table_size, GFP_KERNEL);
  268. if (NULL == tdp_table)
  269. return -ENOMEM;
  270. tdp_table->usTDP = le16_to_cpu(table->usTDP);
  271. tdp_table->usConfigurableTDP = le16_to_cpu(table->usConfigurableTDP);
  272. tdp_table->usTDC = le16_to_cpu(table->usTDC);
  273. tdp_table->usBatteryPowerLimit = le16_to_cpu(table->usBatteryPowerLimit);
  274. tdp_table->usSmallPowerLimit = le16_to_cpu(table->usSmallPowerLimit);
  275. tdp_table->usLowCACLeakage = le16_to_cpu(table->usLowCACLeakage);
  276. tdp_table->usHighCACLeakage = le16_to_cpu(table->usHighCACLeakage);
  277. tdp_table->usMaximumPowerDeliveryLimit = us_maximum_power_delivery_limit;
  278. *ptable = tdp_table;
  279. return 0;
  280. }
  281. static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr *hwmgr,
  282. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  283. {
  284. uint16_t sclk_vdd_gfx_table_offset = 0;
  285. if (le16_to_cpu(powerplay_table->usTableSize) >=
  286. sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
  287. const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
  288. (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
  289. if (powerplay_table3->usExtendendedHeaderOffset > 0) {
  290. const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =
  291. (const ATOM_PPLIB_EXTENDEDHEADER *)
  292. (((unsigned long)powerplay_table3) +
  293. le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
  294. if (le16_to_cpu(pExtendedHeader->usSize) >=
  295. SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8)
  296. sclk_vdd_gfx_table_offset =
  297. le16_to_cpu(pExtendedHeader->usSclkVddgfxTableOffset);
  298. }
  299. }
  300. return sclk_vdd_gfx_table_offset;
  301. }
  302. static uint16_t get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(
  303. struct pp_hwmgr *hwmgr,
  304. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  305. {
  306. uint16_t tableOffset = get_sclk_vdd_gfx_table_offset(hwmgr, powerplay_table);
  307. if (tableOffset > 0)
  308. return tableOffset;
  309. return 0;
  310. }
  311. static int get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr,
  312. struct phm_clock_voltage_dependency_table **ptable,
  313. const ATOM_PPLIB_Clock_Voltage_Dependency_Table *table)
  314. {
  315. unsigned long table_size, i;
  316. struct phm_clock_voltage_dependency_table *dep_table;
  317. table_size = sizeof(unsigned long) +
  318. sizeof(struct phm_clock_voltage_dependency_table)
  319. * table->ucNumEntries;
  320. dep_table = kzalloc(table_size, GFP_KERNEL);
  321. if (NULL == dep_table)
  322. return -ENOMEM;
  323. dep_table->count = (unsigned long)table->ucNumEntries;
  324. for (i = 0; i < dep_table->count; i++) {
  325. dep_table->entries[i].clk =
  326. ((unsigned long)table->entries[i].ucClockHigh << 16) |
  327. le16_to_cpu(table->entries[i].usClockLow);
  328. dep_table->entries[i].v =
  329. (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
  330. }
  331. *ptable = dep_table;
  332. return 0;
  333. }
  334. static int get_valid_clk(struct pp_hwmgr *hwmgr,
  335. struct phm_clock_array **ptable,
  336. const struct phm_clock_voltage_dependency_table *table)
  337. {
  338. unsigned long table_size, i;
  339. struct phm_clock_array *clock_table;
  340. table_size = sizeof(unsigned long) + sizeof(unsigned long) * table->count;
  341. clock_table = kzalloc(table_size, GFP_KERNEL);
  342. if (NULL == clock_table)
  343. return -ENOMEM;
  344. clock_table->count = (unsigned long)table->count;
  345. for (i = 0; i < clock_table->count; i++)
  346. clock_table->values[i] = (unsigned long)table->entries[i].clk;
  347. *ptable = clock_table;
  348. return 0;
  349. }
  350. static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr,
  351. struct phm_clock_and_voltage_limits *limits,
  352. const ATOM_PPLIB_Clock_Voltage_Limit_Table *table)
  353. {
  354. limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) |
  355. le16_to_cpu(table->entries[0].usSclkLow);
  356. limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) |
  357. le16_to_cpu(table->entries[0].usMclkLow);
  358. limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc);
  359. limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci);
  360. return 0;
  361. }
  362. static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
  363. enum phm_platform_caps cap)
  364. {
  365. if (enable)
  366. phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
  367. else
  368. phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
  369. }
  370. static int set_platform_caps(struct pp_hwmgr *hwmgr,
  371. unsigned long powerplay_caps)
  372. {
  373. set_hw_cap(
  374. hwmgr,
  375. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY),
  376. PHM_PlatformCaps_PowerPlaySupport
  377. );
  378. set_hw_cap(
  379. hwmgr,
  380. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
  381. PHM_PlatformCaps_BiosPowerSourceControl
  382. );
  383. set_hw_cap(
  384. hwmgr,
  385. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s),
  386. PHM_PlatformCaps_EnableASPML0s
  387. );
  388. set_hw_cap(
  389. hwmgr,
  390. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1),
  391. PHM_PlatformCaps_EnableASPML1
  392. );
  393. set_hw_cap(
  394. hwmgr,
  395. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS),
  396. PHM_PlatformCaps_EnableBackbias
  397. );
  398. set_hw_cap(
  399. hwmgr,
  400. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC),
  401. PHM_PlatformCaps_AutomaticDCTransition
  402. );
  403. set_hw_cap(
  404. hwmgr,
  405. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY),
  406. PHM_PlatformCaps_GeminiPrimary
  407. );
  408. set_hw_cap(
  409. hwmgr,
  410. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC),
  411. PHM_PlatformCaps_StepVddc
  412. );
  413. set_hw_cap(
  414. hwmgr,
  415. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL),
  416. PHM_PlatformCaps_EnableVoltageControl
  417. );
  418. set_hw_cap(
  419. hwmgr,
  420. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL),
  421. PHM_PlatformCaps_EnableSideportControl
  422. );
  423. set_hw_cap(
  424. hwmgr,
  425. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1),
  426. PHM_PlatformCaps_TurnOffPll_ASPML1
  427. );
  428. set_hw_cap(
  429. hwmgr,
  430. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL),
  431. PHM_PlatformCaps_EnableHTLinkControl
  432. );
  433. set_hw_cap(
  434. hwmgr,
  435. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL),
  436. PHM_PlatformCaps_EnableMVDDControl
  437. );
  438. set_hw_cap(
  439. hwmgr,
  440. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL),
  441. PHM_PlatformCaps_ControlVDDCI
  442. );
  443. set_hw_cap(
  444. hwmgr,
  445. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT),
  446. PHM_PlatformCaps_RegulatorHot
  447. );
  448. set_hw_cap(
  449. hwmgr,
  450. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT),
  451. PHM_PlatformCaps_BootStateOnAlert
  452. );
  453. set_hw_cap(
  454. hwmgr,
  455. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT),
  456. PHM_PlatformCaps_DontWaitForVBlankOnAlert
  457. );
  458. set_hw_cap(
  459. hwmgr,
  460. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO),
  461. PHM_PlatformCaps_BACO
  462. );
  463. set_hw_cap(
  464. hwmgr,
  465. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE),
  466. PHM_PlatformCaps_NewCACVoltage
  467. );
  468. set_hw_cap(
  469. hwmgr,
  470. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY),
  471. PHM_PlatformCaps_RevertGPIO5Polarity
  472. );
  473. set_hw_cap(
  474. hwmgr,
  475. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17),
  476. PHM_PlatformCaps_Thermal2GPIO17
  477. );
  478. set_hw_cap(
  479. hwmgr,
  480. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE),
  481. PHM_PlatformCaps_VRHotGPIOConfigurable
  482. );
  483. set_hw_cap(
  484. hwmgr,
  485. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION),
  486. PHM_PlatformCaps_TempInversion
  487. );
  488. set_hw_cap(
  489. hwmgr,
  490. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV),
  491. PHM_PlatformCaps_EVV
  492. );
  493. set_hw_cap(
  494. hwmgr,
  495. 0 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
  496. PHM_PlatformCaps_CombinePCCWithThermalSignal
  497. );
  498. set_hw_cap(
  499. hwmgr,
  500. 0 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),
  501. PHM_PlatformCaps_LoadPostProductionFirmware
  502. );
  503. set_hw_cap(
  504. hwmgr,
  505. 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC),
  506. PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc
  507. );
  508. return 0;
  509. }
  510. static PP_StateClassificationFlags make_classification_flags(
  511. struct pp_hwmgr *hwmgr,
  512. USHORT classification,
  513. USHORT classification2)
  514. {
  515. PP_StateClassificationFlags result = 0;
  516. if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
  517. result |= PP_StateClassificationFlag_Boot;
  518. if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
  519. result |= PP_StateClassificationFlag_Thermal;
  520. if (classification &
  521. ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
  522. result |= PP_StateClassificationFlag_LimitedPowerSource;
  523. if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
  524. result |= PP_StateClassificationFlag_Rest;
  525. if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
  526. result |= PP_StateClassificationFlag_Forced;
  527. if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
  528. result |= PP_StateClassificationFlag_3DPerformance;
  529. if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
  530. result |= PP_StateClassificationFlag_ACOverdriveTemplate;
  531. if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
  532. result |= PP_StateClassificationFlag_Uvd;
  533. if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
  534. result |= PP_StateClassificationFlag_UvdHD;
  535. if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
  536. result |= PP_StateClassificationFlag_UvdSD;
  537. if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
  538. result |= PP_StateClassificationFlag_HD2;
  539. if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
  540. result |= PP_StateClassificationFlag_ACPI;
  541. if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
  542. result |= PP_StateClassificationFlag_LimitedPowerSource_2;
  543. if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
  544. result |= PP_StateClassificationFlag_ULV;
  545. if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
  546. result |= PP_StateClassificationFlag_UvdMVC;
  547. return result;
  548. }
  549. static int init_non_clock_fields(struct pp_hwmgr *hwmgr,
  550. struct pp_power_state *ps,
  551. uint8_t version,
  552. const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) {
  553. unsigned long rrr_index;
  554. unsigned long tmp;
  555. ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) &
  556. ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
  557. ps->classification.flags = make_classification_flags(hwmgr,
  558. le16_to_cpu(pnon_clock_info->usClassification),
  559. le16_to_cpu(pnon_clock_info->usClassification2));
  560. ps->classification.temporary_state = false;
  561. ps->classification.to_be_deleted = false;
  562. tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
  563. ATOM_PPLIB_SINGLE_DISPLAY_ONLY;
  564. ps->validation.singleDisplayOnly = (0 != tmp);
  565. tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
  566. ATOM_PPLIB_DISALLOW_ON_DC;
  567. ps->validation.disallowOnDC = (0 != tmp);
  568. ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
  569. ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
  570. ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
  571. ps->pcie.lanes = 0;
  572. ps->display.disableFrameModulation = false;
  573. rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
  574. ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >>
  575. ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT;
  576. if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) {
  577. static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \
  578. { 0, 50, 0 };
  579. ps->display.refreshrateSource = PP_RefreshrateSource_Explicit;
  580. ps->display.explicitRefreshrate = look_up[rrr_index];
  581. ps->display.limitRefreshrate = true;
  582. if (ps->display.explicitRefreshrate == 0)
  583. ps->display.limitRefreshrate = false;
  584. } else
  585. ps->display.limitRefreshrate = false;
  586. tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
  587. ATOM_PPLIB_ENABLE_VARIBRIGHT;
  588. ps->display.enableVariBright = (0 != tmp);
  589. tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
  590. ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF;
  591. ps->memory.dllOff = (0 != tmp);
  592. ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
  593. ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT;
  594. ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
  595. pnon_clock_info->ucMinTemperature;
  596. ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
  597. pnon_clock_info->ucMaxTemperature;
  598. tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
  599. ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING;
  600. ps->software.disableLoadBalancing = tmp;
  601. tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
  602. ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS;
  603. ps->software.enableSleepForTimestamps = (0 != tmp);
  604. ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower;
  605. if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) {
  606. ps->uvd_clocks.VCLK = pnon_clock_info->ulVCLK;
  607. ps->uvd_clocks.DCLK = pnon_clock_info->ulDCLK;
  608. } else {
  609. ps->uvd_clocks.VCLK = 0;
  610. ps->uvd_clocks.DCLK = 0;
  611. }
  612. return 0;
  613. }
  614. static ULONG size_of_entry_v2(ULONG num_dpm_levels)
  615. {
  616. return (sizeof(UCHAR) + sizeof(UCHAR) +
  617. (num_dpm_levels * sizeof(UCHAR)));
  618. }
  619. static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2(
  620. const StateArray * pstate_arrays,
  621. ULONG entry_index)
  622. {
  623. ULONG i;
  624. const ATOM_PPLIB_STATE_V2 *pstate;
  625. pstate = pstate_arrays->states;
  626. if (entry_index <= pstate_arrays->ucNumEntries) {
  627. for (i = 0; i < entry_index; i++)
  628. pstate = (ATOM_PPLIB_STATE_V2 *)(
  629. (unsigned long)pstate +
  630. size_of_entry_v2(pstate->ucNumDPMLevels));
  631. }
  632. return pstate;
  633. }
  634. static const unsigned char soft_dummy_pp_table[] = {
  635. 0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00,
  636. 0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
  637. 0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
  638. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  639. 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
  640. 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  641. 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00,
  642. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  643. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  644. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00,
  645. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00,
  646. 0x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
  647. 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00,
  648. 0x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
  649. 0x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59,
  650. 0xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28,
  651. 0x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01,
  652. 0xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01,
  653. 0x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a,
  654. 0x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
  655. 0x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c,
  656. 0x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01,
  657. 0x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e,
  658. 0xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70,
  659. 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08,
  660. 0x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70,
  661. 0x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00,
  662. 0x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
  663. 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00,
  664. 0x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
  665. 0x00
  666. };
  667. static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table(
  668. struct pp_hwmgr *hwmgr)
  669. {
  670. const void *table_addr = hwmgr->soft_pp_table;
  671. uint8_t frev, crev;
  672. uint16_t size;
  673. if (!table_addr) {
  674. if (hwmgr->chip_id == CHIP_RAVEN) {
  675. table_addr = &soft_dummy_pp_table[0];
  676. hwmgr->soft_pp_table = &soft_dummy_pp_table[0];
  677. hwmgr->soft_pp_table_size = sizeof(soft_dummy_pp_table);
  678. } else {
  679. table_addr = smu_atom_get_data_table(hwmgr->adev,
  680. GetIndexIntoMasterTable(DATA, PowerPlayInfo),
  681. &size, &frev, &crev);
  682. hwmgr->soft_pp_table = table_addr;
  683. hwmgr->soft_pp_table_size = size;
  684. }
  685. }
  686. return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr;
  687. }
  688. int pp_tables_get_response_times(struct pp_hwmgr *hwmgr,
  689. uint32_t *vol_rep_time, uint32_t *bb_rep_time)
  690. {
  691. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr);
  692. PP_ASSERT_WITH_CODE(NULL != powerplay_tab,
  693. "Missing PowerPlay Table!", return -EINVAL);
  694. *vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime);
  695. *bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime);
  696. return 0;
  697. }
  698. int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
  699. unsigned long *num_of_entries)
  700. {
  701. const StateArray *pstate_arrays;
  702. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
  703. if (powerplay_table == NULL)
  704. return -1;
  705. if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
  706. pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
  707. le16_to_cpu(powerplay_table->usStateArrayOffset));
  708. *num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries);
  709. } else
  710. *num_of_entries = (unsigned long)(powerplay_table->ucNumStates);
  711. return 0;
  712. }
  713. int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
  714. unsigned long entry_index,
  715. struct pp_power_state *ps,
  716. pp_tables_hw_clock_info_callback func)
  717. {
  718. int i;
  719. const StateArray *pstate_arrays;
  720. const ATOM_PPLIB_STATE_V2 *pstate_entry_v2;
  721. const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info;
  722. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
  723. int result = 0;
  724. int res = 0;
  725. const ClockInfoArray *pclock_arrays;
  726. const NonClockInfoArray *pnon_clock_arrays;
  727. const ATOM_PPLIB_STATE *pstate_entry;
  728. if (powerplay_table == NULL)
  729. return -1;
  730. ps->classification.bios_index = entry_index;
  731. if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
  732. pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
  733. le16_to_cpu(powerplay_table->usStateArrayOffset));
  734. if (entry_index > pstate_arrays->ucNumEntries)
  735. return -1;
  736. pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index);
  737. pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
  738. le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
  739. pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) +
  740. le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset));
  741. pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) +
  742. (pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize));
  743. result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info);
  744. for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) {
  745. const void *pclock_info = (const void *)(
  746. (unsigned long)(pclock_arrays->clockInfo) +
  747. (pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize));
  748. res = func(hwmgr, &ps->hardware, i, pclock_info);
  749. if ((0 == result) && (0 != res))
  750. result = res;
  751. }
  752. } else {
  753. if (entry_index > powerplay_table->ucNumStates)
  754. return -1;
  755. pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table + powerplay_table->usStateArrayOffset +
  756. entry_index * powerplay_table->ucStateEntrySize);
  757. pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
  758. le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
  759. pstate_entry->ucNonClockStateIndex *
  760. powerplay_table->ucNonClockSize);
  761. result = init_non_clock_fields(hwmgr, ps,
  762. powerplay_table->ucNonClockSize,
  763. pnon_clock_info);
  764. for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
  765. const void *pclock_info = (const void *)((unsigned long)powerplay_table +
  766. le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
  767. pstate_entry->ucClockStateIndices[i] *
  768. powerplay_table->ucClockInfoSize);
  769. int res = func(hwmgr, &ps->hardware, i, pclock_info);
  770. if ((0 == result) && (0 != res))
  771. result = res;
  772. }
  773. }
  774. if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) {
  775. if (hwmgr->chip_family < AMDGPU_FAMILY_RV)
  776. result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));
  777. }
  778. return result;
  779. }
  780. static int init_powerplay_tables(
  781. struct pp_hwmgr *hwmgr,
  782. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
  783. )
  784. {
  785. return 0;
  786. }
  787. static int init_thermal_controller(
  788. struct pp_hwmgr *hwmgr,
  789. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  790. {
  791. hwmgr->thermal_controller.ucType =
  792. powerplay_table->sThermalController.ucType;
  793. hwmgr->thermal_controller.ucI2cLine =
  794. powerplay_table->sThermalController.ucI2cLine;
  795. hwmgr->thermal_controller.ucI2cAddress =
  796. powerplay_table->sThermalController.ucI2cAddress;
  797. hwmgr->thermal_controller.fanInfo.bNoFan =
  798. (0 != (powerplay_table->sThermalController.ucFanParameters &
  799. ATOM_PP_FANPARAMETERS_NOFAN));
  800. hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
  801. powerplay_table->sThermalController.ucFanParameters &
  802. ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
  803. hwmgr->thermal_controller.fanInfo.ulMinRPM
  804. = powerplay_table->sThermalController.ucFanMinRPM * 100UL;
  805. hwmgr->thermal_controller.fanInfo.ulMaxRPM
  806. = powerplay_table->sThermalController.ucFanMaxRPM * 100UL;
  807. set_hw_cap(hwmgr,
  808. ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
  809. PHM_PlatformCaps_ThermalController);
  810. hwmgr->thermal_controller.use_hw_fan_control = 1;
  811. return 0;
  812. }
  813. static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
  814. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
  815. const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
  816. {
  817. hwmgr->platform_descriptor.overdriveLimit.engineClock =
  818. le32_to_cpu(fw_info->ulASICMaxEngineClock);
  819. hwmgr->platform_descriptor.overdriveLimit.memoryClock =
  820. le32_to_cpu(fw_info->ulASICMaxMemoryClock);
  821. hwmgr->platform_descriptor.maxOverdriveVDDC =
  822. le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
  823. hwmgr->platform_descriptor.minOverdriveVDDC =
  824. le16_to_cpu(fw_info->usBootUpVDDCVoltage);
  825. hwmgr->platform_descriptor.maxOverdriveVDDC =
  826. le16_to_cpu(fw_info->usBootUpVDDCVoltage);
  827. hwmgr->platform_descriptor.overdriveVDDCStep = 0;
  828. return 0;
  829. }
  830. static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
  831. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
  832. const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
  833. {
  834. const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
  835. const ATOM_PPLIB_EXTENDEDHEADER *header;
  836. if (le16_to_cpu(powerplay_table->usTableSize) <
  837. sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
  838. return 0;
  839. powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
  840. if (0 == powerplay_table3->usExtendendedHeaderOffset)
  841. return 0;
  842. header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
  843. le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
  844. hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
  845. hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
  846. hwmgr->platform_descriptor.minOverdriveVDDC = 0;
  847. hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
  848. hwmgr->platform_descriptor.overdriveVDDCStep = 0;
  849. return 0;
  850. }
  851. static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
  852. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  853. {
  854. int result = 0;
  855. uint8_t frev, crev;
  856. uint16_t size;
  857. const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
  858. hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
  859. hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
  860. hwmgr->platform_descriptor.minOverdriveVDDC = 0;
  861. hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
  862. hwmgr->platform_descriptor.overdriveVDDCStep = 0;
  863. if (hwmgr->chip_id == CHIP_RAVEN)
  864. return 0;
  865. /* We assume here that fw_info is unchanged if this call fails.*/
  866. fw_info = smu_atom_get_data_table(hwmgr->adev,
  867. GetIndexIntoMasterTable(DATA, FirmwareInfo),
  868. &size, &frev, &crev);
  869. if ((fw_info->ucTableFormatRevision == 1)
  870. && (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
  871. result = init_overdrive_limits_V1_4(hwmgr,
  872. powerplay_table,
  873. (const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
  874. else if ((fw_info->ucTableFormatRevision == 2)
  875. && (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
  876. result = init_overdrive_limits_V2_1(hwmgr,
  877. powerplay_table,
  878. (const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
  879. return result;
  880. }
  881. static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
  882. struct phm_uvd_clock_voltage_dependency_table **ptable,
  883. const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
  884. const UVDClockInfoArray *array)
  885. {
  886. unsigned long table_size, i;
  887. struct phm_uvd_clock_voltage_dependency_table *uvd_table;
  888. table_size = sizeof(unsigned long) +
  889. sizeof(struct phm_uvd_clock_voltage_dependency_table) *
  890. table->numEntries;
  891. uvd_table = kzalloc(table_size, GFP_KERNEL);
  892. if (NULL == uvd_table)
  893. return -ENOMEM;
  894. uvd_table->count = table->numEntries;
  895. for (i = 0; i < table->numEntries; i++) {
  896. const UVDClockInfo *entry =
  897. &array->entries[table->entries[i].ucUVDClockInfoIndex];
  898. uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
  899. uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)
  900. | le16_to_cpu(entry->usVClkLow);
  901. uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)
  902. | le16_to_cpu(entry->usDClkLow);
  903. }
  904. *ptable = uvd_table;
  905. return 0;
  906. }
  907. static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
  908. struct phm_vce_clock_voltage_dependency_table **ptable,
  909. const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,
  910. const VCEClockInfoArray *array)
  911. {
  912. unsigned long table_size, i;
  913. struct phm_vce_clock_voltage_dependency_table *vce_table = NULL;
  914. table_size = sizeof(unsigned long) +
  915. sizeof(struct phm_vce_clock_voltage_dependency_table)
  916. * table->numEntries;
  917. vce_table = kzalloc(table_size, GFP_KERNEL);
  918. if (NULL == vce_table)
  919. return -ENOMEM;
  920. vce_table->count = table->numEntries;
  921. for (i = 0; i < table->numEntries; i++) {
  922. const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
  923. vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
  924. vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
  925. | le16_to_cpu(entry->usEVClkLow);
  926. vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
  927. | le16_to_cpu(entry->usECClkLow);
  928. }
  929. *ptable = vce_table;
  930. return 0;
  931. }
  932. static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
  933. struct phm_samu_clock_voltage_dependency_table **ptable,
  934. const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
  935. {
  936. unsigned long table_size, i;
  937. struct phm_samu_clock_voltage_dependency_table *samu_table;
  938. table_size = sizeof(unsigned long) +
  939. sizeof(struct phm_samu_clock_voltage_dependency_table) *
  940. table->numEntries;
  941. samu_table = kzalloc(table_size, GFP_KERNEL);
  942. if (NULL == samu_table)
  943. return -ENOMEM;
  944. samu_table->count = table->numEntries;
  945. for (i = 0; i < table->numEntries; i++) {
  946. samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
  947. samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
  948. | le16_to_cpu(table->entries[i].usSAMClockLow);
  949. }
  950. *ptable = samu_table;
  951. return 0;
  952. }
  953. static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
  954. struct phm_acp_clock_voltage_dependency_table **ptable,
  955. const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
  956. {
  957. unsigned table_size, i;
  958. struct phm_acp_clock_voltage_dependency_table *acp_table;
  959. table_size = sizeof(unsigned long) +
  960. sizeof(struct phm_acp_clock_voltage_dependency_table) *
  961. table->numEntries;
  962. acp_table = kzalloc(table_size, GFP_KERNEL);
  963. if (NULL == acp_table)
  964. return -ENOMEM;
  965. acp_table->count = (unsigned long)table->numEntries;
  966. for (i = 0; i < table->numEntries; i++) {
  967. acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
  968. acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
  969. | le16_to_cpu(table->entries[i].usACPClockLow);
  970. }
  971. *ptable = acp_table;
  972. return 0;
  973. }
  974. static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
  975. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  976. {
  977. ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
  978. ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
  979. int result = 0;
  980. uint16_t vce_clock_info_array_offset;
  981. uint16_t uvd_clock_info_array_offset;
  982. uint16_t table_offset;
  983. hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
  984. hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
  985. hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
  986. hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
  987. hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
  988. hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
  989. hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
  990. hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
  991. hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
  992. hwmgr->dyn_state.ppm_parameter_table = NULL;
  993. hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
  994. vce_clock_info_array_offset = get_vce_clock_info_array_offset(
  995. hwmgr, powerplay_table);
  996. table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
  997. powerplay_table);
  998. if (vce_clock_info_array_offset > 0 && table_offset > 0) {
  999. const VCEClockInfoArray *array = (const VCEClockInfoArray *)
  1000. (((unsigned long) powerplay_table) +
  1001. vce_clock_info_array_offset);
  1002. const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
  1003. (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
  1004. (((unsigned long) powerplay_table) + table_offset);
  1005. result = get_vce_clock_voltage_limit_table(hwmgr,
  1006. &hwmgr->dyn_state.vce_clock_voltage_dependency_table,
  1007. table, array);
  1008. }
  1009. uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
  1010. table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
  1011. if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
  1012. const UVDClockInfoArray *array = (const UVDClockInfoArray *)
  1013. (((unsigned long) powerplay_table) +
  1014. uvd_clock_info_array_offset);
  1015. const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
  1016. (const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
  1017. (((unsigned long) powerplay_table) + table_offset);
  1018. result = get_uvd_clock_voltage_limit_table(hwmgr,
  1019. &hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
  1020. }
  1021. table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
  1022. powerplay_table);
  1023. if (table_offset > 0) {
  1024. const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
  1025. (const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
  1026. (((unsigned long) powerplay_table) + table_offset);
  1027. result = get_samu_clock_voltage_limit_table(hwmgr,
  1028. &hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
  1029. }
  1030. table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
  1031. powerplay_table);
  1032. if (table_offset > 0) {
  1033. const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
  1034. (const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
  1035. (((unsigned long) powerplay_table) + table_offset);
  1036. result = get_acp_clock_voltage_limit_table(hwmgr,
  1037. &hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
  1038. }
  1039. table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
  1040. if (table_offset > 0) {
  1041. UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
  1042. if (rev_id > 0) {
  1043. const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
  1044. (const ATOM_PPLIB_POWERTUNE_Table_V1 *)
  1045. (((unsigned long) powerplay_table) + table_offset);
  1046. result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
  1047. &tune_table->power_tune_table,
  1048. le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
  1049. hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
  1050. le16_to_cpu(tune_table->usTjMax);
  1051. } else {
  1052. const ATOM_PPLIB_POWERTUNE_Table *tune_table =
  1053. (const ATOM_PPLIB_POWERTUNE_Table *)
  1054. (((unsigned long) powerplay_table) + table_offset);
  1055. result = get_cac_tdp_table(hwmgr,
  1056. &hwmgr->dyn_state.cac_dtp_table,
  1057. &tune_table->power_tune_table, 255);
  1058. }
  1059. }
  1060. if (le16_to_cpu(powerplay_table->usTableSize) >=
  1061. sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
  1062. const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
  1063. (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
  1064. if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
  1065. table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
  1066. (((unsigned long) powerplay_table4) +
  1067. powerplay_table4->usVddcDependencyOnSCLKOffset);
  1068. result = get_clock_voltage_dependency_table(hwmgr,
  1069. &hwmgr->dyn_state.vddc_dependency_on_sclk, table);
  1070. }
  1071. if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
  1072. table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
  1073. (((unsigned long) powerplay_table4) +
  1074. powerplay_table4->usVddciDependencyOnMCLKOffset);
  1075. result = get_clock_voltage_dependency_table(hwmgr,
  1076. &hwmgr->dyn_state.vddci_dependency_on_mclk, table);
  1077. }
  1078. if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
  1079. table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
  1080. (((unsigned long) powerplay_table4) +
  1081. powerplay_table4->usVddcDependencyOnMCLKOffset);
  1082. result = get_clock_voltage_dependency_table(hwmgr,
  1083. &hwmgr->dyn_state.vddc_dependency_on_mclk, table);
  1084. }
  1085. if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
  1086. limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
  1087. (((unsigned long) powerplay_table4) +
  1088. powerplay_table4->usMaxClockVoltageOnDCOffset);
  1089. result = get_clock_voltage_limit(hwmgr,
  1090. &hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
  1091. }
  1092. if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
  1093. (0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
  1094. result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
  1095. hwmgr->dyn_state.vddc_dependency_on_mclk);
  1096. if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
  1097. (0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
  1098. result = get_valid_clk(hwmgr,
  1099. &hwmgr->dyn_state.valid_sclk_values,
  1100. hwmgr->dyn_state.vddc_dependency_on_sclk);
  1101. if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
  1102. table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
  1103. (((unsigned long) powerplay_table4) +
  1104. powerplay_table4->usMvddDependencyOnMCLKOffset);
  1105. result = get_clock_voltage_dependency_table(hwmgr,
  1106. &hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
  1107. }
  1108. }
  1109. table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
  1110. powerplay_table);
  1111. if (table_offset > 0) {
  1112. table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
  1113. (((unsigned long) powerplay_table) + table_offset);
  1114. result = get_clock_voltage_dependency_table(hwmgr,
  1115. &hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
  1116. }
  1117. return result;
  1118. }
  1119. static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
  1120. struct phm_cac_leakage_table **ptable,
  1121. const ATOM_PPLIB_CAC_Leakage_Table *table)
  1122. {
  1123. struct phm_cac_leakage_table *cac_leakage_table;
  1124. unsigned long table_size, i;
  1125. if (hwmgr == NULL || table == NULL || ptable == NULL)
  1126. return -EINVAL;
  1127. table_size = sizeof(ULONG) +
  1128. (sizeof(struct phm_cac_leakage_table) * table->ucNumEntries);
  1129. cac_leakage_table = kzalloc(table_size, GFP_KERNEL);
  1130. if (cac_leakage_table == NULL)
  1131. return -ENOMEM;
  1132. cac_leakage_table->count = (ULONG)table->ucNumEntries;
  1133. for (i = 0; i < cac_leakage_table->count; i++) {
  1134. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  1135. PHM_PlatformCaps_EVV)) {
  1136. cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
  1137. cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
  1138. cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
  1139. } else {
  1140. cac_leakage_table->entries[i].Vddc = le16_to_cpu(table->entries[i].usVddc);
  1141. cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
  1142. }
  1143. }
  1144. *ptable = cac_leakage_table;
  1145. return 0;
  1146. }
  1147. static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
  1148. ATOM_PPLIB_PPM_Table *atom_ppm_table)
  1149. {
  1150. struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);
  1151. if (NULL == ptr)
  1152. return -ENOMEM;
  1153. ptr->ppm_design = atom_ppm_table->ucPpmDesign;
  1154. ptr->cpu_core_number = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
  1155. ptr->platform_tdp = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
  1156. ptr->small_ac_platform_tdp = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
  1157. ptr->platform_tdc = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
  1158. ptr->small_ac_platform_tdc = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
  1159. ptr->apu_tdp = le32_to_cpu(atom_ppm_table->ulApuTDP);
  1160. ptr->dgpu_tdp = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
  1161. ptr->dgpu_ulv_power = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
  1162. ptr->tj_max = le32_to_cpu(atom_ppm_table->ulTjmax);
  1163. hwmgr->dyn_state.ppm_parameter_table = ptr;
  1164. return 0;
  1165. }
  1166. static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
  1167. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  1168. {
  1169. int result = 0;
  1170. if (le16_to_cpu(powerplay_table->usTableSize) >=
  1171. sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
  1172. const ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
  1173. (const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
  1174. const ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
  1175. (const ATOM_PPLIB_POWERPLAYTABLE4 *)
  1176. (&ptable5->basicTable4);
  1177. const ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
  1178. (const ATOM_PPLIB_POWERPLAYTABLE3 *)
  1179. (&ptable4->basicTable3);
  1180. const ATOM_PPLIB_EXTENDEDHEADER *extended_header;
  1181. uint16_t table_offset;
  1182. ATOM_PPLIB_PPM_Table *atom_ppm_table;
  1183. hwmgr->platform_descriptor.TDPLimit = le32_to_cpu(ptable5->ulTDPLimit);
  1184. hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
  1185. hwmgr->platform_descriptor.TDPODLimit = le16_to_cpu(ptable5->usTDPODLimit);
  1186. hwmgr->platform_descriptor.TDPAdjustment = 0;
  1187. hwmgr->platform_descriptor.VidAdjustment = 0;
  1188. hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
  1189. hwmgr->platform_descriptor.VidMinLimit = 0;
  1190. hwmgr->platform_descriptor.VidMaxLimit = 1500000;
  1191. hwmgr->platform_descriptor.VidStep = 6250;
  1192. hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
  1193. if (hwmgr->platform_descriptor.TDPODLimit != 0)
  1194. phm_cap_set(hwmgr->platform_descriptor.platformCaps,
  1195. PHM_PlatformCaps_PowerControl);
  1196. hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
  1197. hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
  1198. hwmgr->dyn_state.cac_leakage_table = NULL;
  1199. if (0 != ptable5->usCACLeakageTableOffset) {
  1200. const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
  1201. (ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
  1202. le16_to_cpu(ptable5->usCACLeakageTableOffset));
  1203. result = get_cac_leakage_table(hwmgr,
  1204. &hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
  1205. }
  1206. hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
  1207. hwmgr->dyn_state.ppm_parameter_table = NULL;
  1208. if (0 != ptable3->usExtendendedHeaderOffset) {
  1209. extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
  1210. (((unsigned long)powerplay_table) +
  1211. le16_to_cpu(ptable3->usExtendendedHeaderOffset));
  1212. if ((extended_header->usPPMTableOffset > 0) &&
  1213. le16_to_cpu(extended_header->usSize) >=
  1214. SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
  1215. table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
  1216. atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
  1217. (((unsigned long)powerplay_table) + table_offset);
  1218. if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
  1219. phm_cap_set(hwmgr->platform_descriptor.platformCaps,
  1220. PHM_PlatformCaps_EnablePlatformPowerManagement);
  1221. }
  1222. }
  1223. }
  1224. return result;
  1225. }
  1226. static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
  1227. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
  1228. {
  1229. if (le16_to_cpu(powerplay_table->usTableSize) >=
  1230. sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
  1231. const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
  1232. (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
  1233. if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
  1234. const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
  1235. (ATOM_PPLIB_PhaseSheddingLimits_Table *)
  1236. (((unsigned long)powerplay_table4) +
  1237. le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
  1238. struct phm_phase_shedding_limits_table *table;
  1239. unsigned long size, i;
  1240. size = sizeof(unsigned long) +
  1241. (sizeof(struct phm_phase_shedding_limits_table) *
  1242. ptable->ucNumEntries);
  1243. table = kzalloc(size, GFP_KERNEL);
  1244. if (table == NULL)
  1245. return -ENOMEM;
  1246. table->count = (unsigned long)ptable->ucNumEntries;
  1247. for (i = 0; i < table->count; i++) {
  1248. table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
  1249. table->entries[i].Sclk = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
  1250. | le16_to_cpu(ptable->entries[i].usSclkLow);
  1251. table->entries[i].Mclk = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
  1252. | le16_to_cpu(ptable->entries[i].usMclkLow);
  1253. }
  1254. hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
  1255. }
  1256. }
  1257. return 0;
  1258. }
  1259. static int get_number_of_vce_state_table_entries(
  1260. struct pp_hwmgr *hwmgr)
  1261. {
  1262. const ATOM_PPLIB_POWERPLAYTABLE *table =
  1263. get_powerplay_table(hwmgr);
  1264. const ATOM_PPLIB_VCE_State_Table *vce_table =
  1265. get_vce_state_table(hwmgr, table);
  1266. if (vce_table)
  1267. return vce_table->numEntries;
  1268. return 0;
  1269. }
  1270. static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
  1271. unsigned long i,
  1272. struct amd_vce_state *vce_state,
  1273. void **clock_info,
  1274. unsigned long *flag)
  1275. {
  1276. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
  1277. const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
  1278. unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
  1279. const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
  1280. const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + powerplay_table->usClockInfoArrayOffset);
  1281. const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
  1282. const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
  1283. unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
  1284. *flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
  1285. vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | vce_clock_info->usEVClkLow;
  1286. vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | vce_clock_info->usECClkLow;
  1287. *clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
  1288. return 0;
  1289. }
  1290. static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
  1291. {
  1292. int result;
  1293. const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
  1294. if (hwmgr->chip_id == CHIP_RAVEN)
  1295. return 0;
  1296. hwmgr->need_pp_table_upload = true;
  1297. powerplay_table = get_powerplay_table(hwmgr);
  1298. result = init_powerplay_tables(hwmgr, powerplay_table);
  1299. PP_ASSERT_WITH_CODE((result == 0),
  1300. "init_powerplay_tables failed", return result);
  1301. result = set_platform_caps(hwmgr,
  1302. le32_to_cpu(powerplay_table->ulPlatformCaps));
  1303. PP_ASSERT_WITH_CODE((result == 0),
  1304. "set_platform_caps failed", return result);
  1305. result = init_thermal_controller(hwmgr, powerplay_table);
  1306. PP_ASSERT_WITH_CODE((result == 0),
  1307. "init_thermal_controller failed", return result);
  1308. result = init_overdrive_limits(hwmgr, powerplay_table);
  1309. PP_ASSERT_WITH_CODE((result == 0),
  1310. "init_overdrive_limits failed", return result);
  1311. result = init_clock_voltage_dependency(hwmgr,
  1312. powerplay_table);
  1313. PP_ASSERT_WITH_CODE((result == 0),
  1314. "init_clock_voltage_dependency failed", return result);
  1315. result = init_dpm2_parameters(hwmgr, powerplay_table);
  1316. PP_ASSERT_WITH_CODE((result == 0),
  1317. "init_dpm2_parameters failed", return result);
  1318. result = init_phase_shedding_table(hwmgr, powerplay_table);
  1319. PP_ASSERT_WITH_CODE((result == 0),
  1320. "init_phase_shedding_table failed", return result);
  1321. return result;
  1322. }
  1323. static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
  1324. {
  1325. if (hwmgr->chip_id == CHIP_RAVEN)
  1326. return 0;
  1327. kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
  1328. hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
  1329. kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
  1330. hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
  1331. kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
  1332. hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
  1333. kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
  1334. hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
  1335. kfree(hwmgr->dyn_state.valid_mclk_values);
  1336. hwmgr->dyn_state.valid_mclk_values = NULL;
  1337. kfree(hwmgr->dyn_state.valid_sclk_values);
  1338. hwmgr->dyn_state.valid_sclk_values = NULL;
  1339. kfree(hwmgr->dyn_state.cac_leakage_table);
  1340. hwmgr->dyn_state.cac_leakage_table = NULL;
  1341. kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
  1342. hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
  1343. kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
  1344. hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
  1345. kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
  1346. hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
  1347. kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
  1348. hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
  1349. kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
  1350. hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
  1351. kfree(hwmgr->dyn_state.cac_dtp_table);
  1352. hwmgr->dyn_state.cac_dtp_table = NULL;
  1353. kfree(hwmgr->dyn_state.ppm_parameter_table);
  1354. hwmgr->dyn_state.ppm_parameter_table = NULL;
  1355. kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
  1356. hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
  1357. return 0;
  1358. }
  1359. const struct pp_table_func pptable_funcs = {
  1360. .pptable_init = pp_tables_initialize,
  1361. .pptable_fini = pp_tables_uninitialize,
  1362. .pptable_get_number_of_vce_state_table_entries =
  1363. get_number_of_vce_state_table_entries,
  1364. .pptable_get_vce_state_table_entry =
  1365. get_vce_state_table_entry,
  1366. };