processpptables.c 53 KB

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