dcn10_hubbub.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. /*
  2. * Copyright 2016 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. * Authors: AMD
  23. *
  24. */
  25. #include "dm_services.h"
  26. #include "dcn10_hubp.h"
  27. #include "dcn10_hubbub.h"
  28. #include "reg_helper.h"
  29. #define CTX \
  30. hubbub->ctx
  31. #define DC_LOGGER \
  32. hubbub->ctx->logger
  33. #define REG(reg)\
  34. hubbub->regs->reg
  35. #undef FN
  36. #define FN(reg_name, field_name) \
  37. hubbub->shifts->field_name, hubbub->masks->field_name
  38. void hubbub1_wm_read_state(struct hubbub *hubbub,
  39. struct dcn_hubbub_wm *wm)
  40. {
  41. struct dcn_hubbub_wm_set *s;
  42. memset(wm, 0, sizeof(struct dcn_hubbub_wm));
  43. s = &wm->sets[0];
  44. s->wm_set = 0;
  45. s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A);
  46. s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A);
  47. if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) {
  48. s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A);
  49. s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A);
  50. }
  51. s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A);
  52. s = &wm->sets[1];
  53. s->wm_set = 1;
  54. s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B);
  55. s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B);
  56. if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) {
  57. s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B);
  58. s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B);
  59. }
  60. s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B);
  61. s = &wm->sets[2];
  62. s->wm_set = 2;
  63. s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C);
  64. s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C);
  65. if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) {
  66. s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C);
  67. s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C);
  68. }
  69. s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C);
  70. s = &wm->sets[3];
  71. s->wm_set = 3;
  72. s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D);
  73. s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D);
  74. if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) {
  75. s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D);
  76. s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D);
  77. }
  78. s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D);
  79. }
  80. void hubbub1_disable_allow_self_refresh(struct hubbub *hubbub)
  81. {
  82. REG_UPDATE(DCHUBBUB_ARB_DRAM_STATE_CNTL,
  83. DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, 0);
  84. }
  85. bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubbub)
  86. {
  87. uint32_t enable = 0;
  88. REG_GET(DCHUBBUB_ARB_DRAM_STATE_CNTL,
  89. DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, &enable);
  90. return true ? false : enable;
  91. }
  92. bool hubbub1_verify_allow_pstate_change_high(
  93. struct hubbub *hubbub)
  94. {
  95. /* pstate latency is ~20us so if we wait over 40us and pstate allow
  96. * still not asserted, we are probably stuck and going to hang
  97. *
  98. * TODO: Figure out why it takes ~100us on linux
  99. * pstate takes around ~100us on linux. Unknown currently as to
  100. * why it takes that long on linux
  101. */
  102. static unsigned int pstate_wait_timeout_us = 200;
  103. static unsigned int pstate_wait_expected_timeout_us = 40;
  104. static unsigned int max_sampled_pstate_wait_us; /* data collection */
  105. static bool forced_pstate_allow; /* help with revert wa */
  106. unsigned int debug_data;
  107. unsigned int i;
  108. if (forced_pstate_allow) {
  109. /* we hacked to force pstate allow to prevent hang last time
  110. * we verify_allow_pstate_change_high. so disable force
  111. * here so we can check status
  112. */
  113. REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
  114. DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0,
  115. DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0);
  116. forced_pstate_allow = false;
  117. }
  118. /* RV2:
  119. * dchubbubdebugind, at: 0xB
  120. * description
  121. * 0: Pipe0 Plane0 Allow Pstate Change
  122. * 1: Pipe0 Plane1 Allow Pstate Change
  123. * 2: Pipe0 Cursor0 Allow Pstate Change
  124. * 3: Pipe0 Cursor1 Allow Pstate Change
  125. * 4: Pipe1 Plane0 Allow Pstate Change
  126. * 5: Pipe1 Plane1 Allow Pstate Change
  127. * 6: Pipe1 Cursor0 Allow Pstate Change
  128. * 7: Pipe1 Cursor1 Allow Pstate Change
  129. * 8: Pipe2 Plane0 Allow Pstate Change
  130. * 9: Pipe2 Plane1 Allow Pstate Change
  131. * 10: Pipe2 Cursor0 Allow Pstate Change
  132. * 11: Pipe2 Cursor1 Allow Pstate Change
  133. * 12: Pipe3 Plane0 Allow Pstate Change
  134. * 13: Pipe3 Plane1 Allow Pstate Change
  135. * 14: Pipe3 Cursor0 Allow Pstate Change
  136. * 15: Pipe3 Cursor1 Allow Pstate Change
  137. * 16: Pipe4 Plane0 Allow Pstate Change
  138. * 17: Pipe4 Plane1 Allow Pstate Change
  139. * 18: Pipe4 Cursor0 Allow Pstate Change
  140. * 19: Pipe4 Cursor1 Allow Pstate Change
  141. * 20: Pipe5 Plane0 Allow Pstate Change
  142. * 21: Pipe5 Plane1 Allow Pstate Change
  143. * 22: Pipe5 Cursor0 Allow Pstate Change
  144. * 23: Pipe5 Cursor1 Allow Pstate Change
  145. * 24: Pipe6 Plane0 Allow Pstate Change
  146. * 25: Pipe6 Plane1 Allow Pstate Change
  147. * 26: Pipe6 Cursor0 Allow Pstate Change
  148. * 27: Pipe6 Cursor1 Allow Pstate Change
  149. * 28: WB0 Allow Pstate Change
  150. * 29: WB1 Allow Pstate Change
  151. * 30: Arbiter's allow_pstate_change
  152. * 31: SOC pstate change request"
  153. *
  154. * RV1:
  155. * dchubbubdebugind, at: 0x7
  156. * description "3-0: Pipe0 cursor0 QOS
  157. * 7-4: Pipe1 cursor0 QOS
  158. * 11-8: Pipe2 cursor0 QOS
  159. * 15-12: Pipe3 cursor0 QOS
  160. * 16: Pipe0 Plane0 Allow Pstate Change
  161. * 17: Pipe1 Plane0 Allow Pstate Change
  162. * 18: Pipe2 Plane0 Allow Pstate Change
  163. * 19: Pipe3 Plane0 Allow Pstate Change
  164. * 20: Pipe0 Plane1 Allow Pstate Change
  165. * 21: Pipe1 Plane1 Allow Pstate Change
  166. * 22: Pipe2 Plane1 Allow Pstate Change
  167. * 23: Pipe3 Plane1 Allow Pstate Change
  168. * 24: Pipe0 cursor0 Allow Pstate Change
  169. * 25: Pipe1 cursor0 Allow Pstate Change
  170. * 26: Pipe2 cursor0 Allow Pstate Change
  171. * 27: Pipe3 cursor0 Allow Pstate Change
  172. * 28: WB0 Allow Pstate Change
  173. * 29: WB1 Allow Pstate Change
  174. * 30: Arbiter's allow_pstate_change
  175. * 31: SOC pstate change request
  176. */
  177. REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub->debug_test_index_pstate);
  178. for (i = 0; i < pstate_wait_timeout_us; i++) {
  179. debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA);
  180. if (debug_data & (1 << 30)) {
  181. if (i > pstate_wait_expected_timeout_us)
  182. DC_LOG_WARNING("pstate took longer than expected ~%dus\n",
  183. i);
  184. return true;
  185. }
  186. if (max_sampled_pstate_wait_us < i)
  187. max_sampled_pstate_wait_us = i;
  188. udelay(1);
  189. }
  190. /* force pstate allow to prevent system hang
  191. * and break to debugger to investigate
  192. */
  193. REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
  194. DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1,
  195. DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1);
  196. forced_pstate_allow = true;
  197. DC_LOG_WARNING("pstate TEST_DEBUG_DATA: 0x%X\n",
  198. debug_data);
  199. return false;
  200. }
  201. static uint32_t convert_and_clamp(
  202. uint32_t wm_ns,
  203. uint32_t refclk_mhz,
  204. uint32_t clamp_value)
  205. {
  206. uint32_t ret_val = 0;
  207. ret_val = wm_ns * refclk_mhz;
  208. ret_val /= 1000;
  209. if (ret_val > clamp_value)
  210. ret_val = clamp_value;
  211. return ret_val;
  212. }
  213. void hubbub1_wm_change_req_wa(struct hubbub *hubbub)
  214. {
  215. REG_UPDATE_SEQ(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
  216. DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0, 1);
  217. }
  218. void hubbub1_program_watermarks(
  219. struct hubbub *hubbub,
  220. struct dcn_watermark_set *watermarks,
  221. unsigned int refclk_mhz,
  222. bool safe_to_lower)
  223. {
  224. uint32_t force_en = hubbub->ctx->dc->debug.disable_stutter ? 1 : 0;
  225. /*
  226. * Need to clamp to max of the register values (i.e. no wrap)
  227. * for dcn1, all wm registers are 21-bit wide
  228. */
  229. uint32_t prog_wm_value;
  230. /* Repeat for water mark set A, B, C and D. */
  231. /* clock state A */
  232. if (safe_to_lower || watermarks->a.urgent_ns > hubbub->watermarks.a.urgent_ns) {
  233. hubbub->watermarks.a.urgent_ns = watermarks->a.urgent_ns;
  234. prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,
  235. refclk_mhz, 0x1fffff);
  236. REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);
  237. DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"
  238. "HW register value = 0x%x\n",
  239. watermarks->a.urgent_ns, prog_wm_value);
  240. }
  241. if (safe_to_lower || watermarks->a.pte_meta_urgent_ns > hubbub->watermarks.a.pte_meta_urgent_ns) {
  242. hubbub->watermarks.a.pte_meta_urgent_ns = watermarks->a.pte_meta_urgent_ns;
  243. prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns,
  244. refclk_mhz, 0x1fffff);
  245. REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value);
  246. DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_A calculated =%d\n"
  247. "HW register value = 0x%x\n",
  248. watermarks->a.pte_meta_urgent_ns, prog_wm_value);
  249. }
  250. if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) {
  251. if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
  252. > hubbub->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) {
  253. hubbub->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =
  254. watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;
  255. prog_wm_value = convert_and_clamp(
  256. watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,
  257. refclk_mhz, 0x1fffff);
  258. REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);
  259. DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
  260. "HW register value = 0x%x\n",
  261. watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
  262. }
  263. if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns
  264. > hubbub->watermarks.a.cstate_pstate.cstate_exit_ns) {
  265. hubbub->watermarks.a.cstate_pstate.cstate_exit_ns =
  266. watermarks->a.cstate_pstate.cstate_exit_ns;
  267. prog_wm_value = convert_and_clamp(
  268. watermarks->a.cstate_pstate.cstate_exit_ns,
  269. refclk_mhz, 0x1fffff);
  270. REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
  271. DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
  272. "HW register value = 0x%x\n",
  273. watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);
  274. }
  275. }
  276. if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns
  277. > hubbub->watermarks.a.cstate_pstate.pstate_change_ns) {
  278. hubbub->watermarks.a.cstate_pstate.pstate_change_ns =
  279. watermarks->a.cstate_pstate.pstate_change_ns;
  280. prog_wm_value = convert_and_clamp(
  281. watermarks->a.cstate_pstate.pstate_change_ns,
  282. refclk_mhz, 0x1fffff);
  283. REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value);
  284. DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
  285. "HW register value = 0x%x\n\n",
  286. watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);
  287. }
  288. /* clock state B */
  289. if (safe_to_lower || watermarks->b.urgent_ns > hubbub->watermarks.b.urgent_ns) {
  290. hubbub->watermarks.b.urgent_ns = watermarks->b.urgent_ns;
  291. prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns,
  292. refclk_mhz, 0x1fffff);
  293. REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value);
  294. DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"
  295. "HW register value = 0x%x\n",
  296. watermarks->b.urgent_ns, prog_wm_value);
  297. }
  298. if (safe_to_lower || watermarks->b.pte_meta_urgent_ns > hubbub->watermarks.b.pte_meta_urgent_ns) {
  299. hubbub->watermarks.b.pte_meta_urgent_ns = watermarks->b.pte_meta_urgent_ns;
  300. prog_wm_value = convert_and_clamp(watermarks->b.pte_meta_urgent_ns,
  301. refclk_mhz, 0x1fffff);
  302. REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value);
  303. DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_B calculated =%d\n"
  304. "HW register value = 0x%x\n",
  305. watermarks->b.pte_meta_urgent_ns, prog_wm_value);
  306. }
  307. if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) {
  308. if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
  309. > hubbub->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) {
  310. hubbub->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns =
  311. watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;
  312. prog_wm_value = convert_and_clamp(
  313. watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,
  314. refclk_mhz, 0x1fffff);
  315. REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);
  316. DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"
  317. "HW register value = 0x%x\n",
  318. watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
  319. }
  320. if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns
  321. > hubbub->watermarks.b.cstate_pstate.cstate_exit_ns) {
  322. hubbub->watermarks.b.cstate_pstate.cstate_exit_ns =
  323. watermarks->b.cstate_pstate.cstate_exit_ns;
  324. prog_wm_value = convert_and_clamp(
  325. watermarks->b.cstate_pstate.cstate_exit_ns,
  326. refclk_mhz, 0x1fffff);
  327. REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value);
  328. DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
  329. "HW register value = 0x%x\n",
  330. watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);
  331. }
  332. }
  333. if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns
  334. > hubbub->watermarks.b.cstate_pstate.pstate_change_ns) {
  335. hubbub->watermarks.b.cstate_pstate.pstate_change_ns =
  336. watermarks->b.cstate_pstate.pstate_change_ns;
  337. prog_wm_value = convert_and_clamp(
  338. watermarks->b.cstate_pstate.pstate_change_ns,
  339. refclk_mhz, 0x1fffff);
  340. REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value);
  341. DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"
  342. "HW register value = 0x%x\n\n",
  343. watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);
  344. }
  345. /* clock state C */
  346. if (safe_to_lower || watermarks->c.urgent_ns > hubbub->watermarks.c.urgent_ns) {
  347. hubbub->watermarks.c.urgent_ns = watermarks->c.urgent_ns;
  348. prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns,
  349. refclk_mhz, 0x1fffff);
  350. REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value);
  351. DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"
  352. "HW register value = 0x%x\n",
  353. watermarks->c.urgent_ns, prog_wm_value);
  354. }
  355. if (safe_to_lower || watermarks->c.pte_meta_urgent_ns > hubbub->watermarks.c.pte_meta_urgent_ns) {
  356. hubbub->watermarks.c.pte_meta_urgent_ns = watermarks->c.pte_meta_urgent_ns;
  357. prog_wm_value = convert_and_clamp(watermarks->c.pte_meta_urgent_ns,
  358. refclk_mhz, 0x1fffff);
  359. REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value);
  360. DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_C calculated =%d\n"
  361. "HW register value = 0x%x\n",
  362. watermarks->c.pte_meta_urgent_ns, prog_wm_value);
  363. }
  364. if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) {
  365. if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
  366. > hubbub->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) {
  367. hubbub->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns =
  368. watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;
  369. prog_wm_value = convert_and_clamp(
  370. watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,
  371. refclk_mhz, 0x1fffff);
  372. REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);
  373. DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"
  374. "HW register value = 0x%x\n",
  375. watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
  376. }
  377. if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns
  378. > hubbub->watermarks.c.cstate_pstate.cstate_exit_ns) {
  379. hubbub->watermarks.c.cstate_pstate.cstate_exit_ns =
  380. watermarks->c.cstate_pstate.cstate_exit_ns;
  381. prog_wm_value = convert_and_clamp(
  382. watermarks->c.cstate_pstate.cstate_exit_ns,
  383. refclk_mhz, 0x1fffff);
  384. REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value);
  385. DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
  386. "HW register value = 0x%x\n",
  387. watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);
  388. }
  389. }
  390. if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns
  391. > hubbub->watermarks.c.cstate_pstate.pstate_change_ns) {
  392. hubbub->watermarks.c.cstate_pstate.pstate_change_ns =
  393. watermarks->c.cstate_pstate.pstate_change_ns;
  394. prog_wm_value = convert_and_clamp(
  395. watermarks->c.cstate_pstate.pstate_change_ns,
  396. refclk_mhz, 0x1fffff);
  397. REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value);
  398. DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"
  399. "HW register value = 0x%x\n\n",
  400. watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);
  401. }
  402. /* clock state D */
  403. if (safe_to_lower || watermarks->d.urgent_ns > hubbub->watermarks.d.urgent_ns) {
  404. hubbub->watermarks.d.urgent_ns = watermarks->d.urgent_ns;
  405. prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns,
  406. refclk_mhz, 0x1fffff);
  407. REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value);
  408. DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"
  409. "HW register value = 0x%x\n",
  410. watermarks->d.urgent_ns, prog_wm_value);
  411. }
  412. if (safe_to_lower || watermarks->d.pte_meta_urgent_ns > hubbub->watermarks.d.pte_meta_urgent_ns) {
  413. hubbub->watermarks.d.pte_meta_urgent_ns = watermarks->d.pte_meta_urgent_ns;
  414. prog_wm_value = convert_and_clamp(watermarks->d.pte_meta_urgent_ns,
  415. refclk_mhz, 0x1fffff);
  416. REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value);
  417. DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_D calculated =%d\n"
  418. "HW register value = 0x%x\n",
  419. watermarks->d.pte_meta_urgent_ns, prog_wm_value);
  420. }
  421. if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) {
  422. if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
  423. > hubbub->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) {
  424. hubbub->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns =
  425. watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;
  426. prog_wm_value = convert_and_clamp(
  427. watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,
  428. refclk_mhz, 0x1fffff);
  429. REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);
  430. DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"
  431. "HW register value = 0x%x\n",
  432. watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
  433. }
  434. if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns
  435. > hubbub->watermarks.d.cstate_pstate.cstate_exit_ns) {
  436. hubbub->watermarks.d.cstate_pstate.cstate_exit_ns =
  437. watermarks->d.cstate_pstate.cstate_exit_ns;
  438. prog_wm_value = convert_and_clamp(
  439. watermarks->d.cstate_pstate.cstate_exit_ns,
  440. refclk_mhz, 0x1fffff);
  441. REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value);
  442. DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
  443. "HW register value = 0x%x\n",
  444. watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);
  445. }
  446. }
  447. if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns
  448. > hubbub->watermarks.d.cstate_pstate.pstate_change_ns) {
  449. hubbub->watermarks.d.cstate_pstate.pstate_change_ns =
  450. watermarks->d.cstate_pstate.pstate_change_ns;
  451. prog_wm_value = convert_and_clamp(
  452. watermarks->d.cstate_pstate.pstate_change_ns,
  453. refclk_mhz, 0x1fffff);
  454. REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value);
  455. DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
  456. "HW register value = 0x%x\n\n",
  457. watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);
  458. }
  459. REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL,
  460. DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
  461. REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
  462. DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68);
  463. REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
  464. DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0,
  465. DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, force_en);
  466. #if 0
  467. REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
  468. DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1,
  469. DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1);
  470. #endif
  471. }
  472. void hubbub1_update_dchub(
  473. struct hubbub *hubbub,
  474. struct dchub_init_data *dh_data)
  475. {
  476. if (REG(DCHUBBUB_SDPIF_FB_TOP) == 0) {
  477. ASSERT(false);
  478. /*should not come here*/
  479. return;
  480. }
  481. /* TODO: port code from dal2 */
  482. switch (dh_data->fb_mode) {
  483. case FRAME_BUFFER_MODE_ZFB_ONLY:
  484. /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/
  485. REG_UPDATE(DCHUBBUB_SDPIF_FB_TOP,
  486. SDPIF_FB_TOP, 0);
  487. REG_UPDATE(DCHUBBUB_SDPIF_FB_BASE,
  488. SDPIF_FB_BASE, 0x0FFFF);
  489. REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE,
  490. SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22);
  491. REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT,
  492. SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22);
  493. REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP,
  494. SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr +
  495. dh_data->zfb_size_in_byte - 1) >> 22);
  496. break;
  497. case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL:
  498. /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/
  499. REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE,
  500. SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22);
  501. REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT,
  502. SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22);
  503. REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP,
  504. SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr +
  505. dh_data->zfb_size_in_byte - 1) >> 22);
  506. break;
  507. case FRAME_BUFFER_MODE_LOCAL_ONLY:
  508. /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/
  509. REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE,
  510. SDPIF_AGP_BASE, 0);
  511. REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT,
  512. SDPIF_AGP_BOT, 0X03FFFF);
  513. REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP,
  514. SDPIF_AGP_TOP, 0);
  515. break;
  516. default:
  517. break;
  518. }
  519. dh_data->dchub_initialzied = true;
  520. dh_data->dchub_info_valid = false;
  521. }
  522. void hubbub1_toggle_watermark_change_req(struct hubbub *hubbub)
  523. {
  524. uint32_t watermark_change_req;
  525. REG_GET(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
  526. DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, &watermark_change_req);
  527. if (watermark_change_req)
  528. watermark_change_req = 0;
  529. else
  530. watermark_change_req = 1;
  531. REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
  532. DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req);
  533. }
  534. void hubbub1_soft_reset(struct hubbub *hubbub, bool reset)
  535. {
  536. uint32_t reset_en = reset ? 1 : 0;
  537. REG_UPDATE(DCHUBBUB_SOFT_RESET,
  538. DCHUBBUB_GLOBAL_SOFT_RESET, reset_en);
  539. }
  540. static bool hubbub1_dcc_support_swizzle(
  541. enum swizzle_mode_values swizzle,
  542. unsigned int bytes_per_element,
  543. enum segment_order *segment_order_horz,
  544. enum segment_order *segment_order_vert)
  545. {
  546. bool standard_swizzle = false;
  547. bool display_swizzle = false;
  548. switch (swizzle) {
  549. case DC_SW_4KB_S:
  550. case DC_SW_64KB_S:
  551. case DC_SW_VAR_S:
  552. case DC_SW_4KB_S_X:
  553. case DC_SW_64KB_S_X:
  554. case DC_SW_VAR_S_X:
  555. standard_swizzle = true;
  556. break;
  557. case DC_SW_4KB_D:
  558. case DC_SW_64KB_D:
  559. case DC_SW_VAR_D:
  560. case DC_SW_4KB_D_X:
  561. case DC_SW_64KB_D_X:
  562. case DC_SW_VAR_D_X:
  563. display_swizzle = true;
  564. break;
  565. default:
  566. break;
  567. }
  568. if (bytes_per_element == 1 && standard_swizzle) {
  569. *segment_order_horz = segment_order__contiguous;
  570. *segment_order_vert = segment_order__na;
  571. return true;
  572. }
  573. if (bytes_per_element == 2 && standard_swizzle) {
  574. *segment_order_horz = segment_order__non_contiguous;
  575. *segment_order_vert = segment_order__contiguous;
  576. return true;
  577. }
  578. if (bytes_per_element == 4 && standard_swizzle) {
  579. *segment_order_horz = segment_order__non_contiguous;
  580. *segment_order_vert = segment_order__contiguous;
  581. return true;
  582. }
  583. if (bytes_per_element == 8 && standard_swizzle) {
  584. *segment_order_horz = segment_order__na;
  585. *segment_order_vert = segment_order__contiguous;
  586. return true;
  587. }
  588. if (bytes_per_element == 8 && display_swizzle) {
  589. *segment_order_horz = segment_order__contiguous;
  590. *segment_order_vert = segment_order__non_contiguous;
  591. return true;
  592. }
  593. return false;
  594. }
  595. static bool hubbub1_dcc_support_pixel_format(
  596. enum surface_pixel_format format,
  597. unsigned int *bytes_per_element)
  598. {
  599. /* DML: get_bytes_per_element */
  600. switch (format) {
  601. case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
  602. case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
  603. *bytes_per_element = 2;
  604. return true;
  605. case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
  606. case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
  607. case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
  608. case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
  609. *bytes_per_element = 4;
  610. return true;
  611. case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
  612. case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
  613. case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
  614. *bytes_per_element = 8;
  615. return true;
  616. default:
  617. return false;
  618. }
  619. }
  620. static void hubbub1_get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height,
  621. unsigned int bytes_per_element)
  622. {
  623. /* copied from DML. might want to refactor DML to leverage from DML */
  624. /* DML : get_blk256_size */
  625. if (bytes_per_element == 1) {
  626. *blk256_width = 16;
  627. *blk256_height = 16;
  628. } else if (bytes_per_element == 2) {
  629. *blk256_width = 16;
  630. *blk256_height = 8;
  631. } else if (bytes_per_element == 4) {
  632. *blk256_width = 8;
  633. *blk256_height = 8;
  634. } else if (bytes_per_element == 8) {
  635. *blk256_width = 8;
  636. *blk256_height = 4;
  637. }
  638. }
  639. static void hubbub1_det_request_size(
  640. unsigned int height,
  641. unsigned int width,
  642. unsigned int bpe,
  643. bool *req128_horz_wc,
  644. bool *req128_vert_wc)
  645. {
  646. unsigned int detile_buf_size = 164 * 1024; /* 164KB for DCN1.0 */
  647. unsigned int blk256_height = 0;
  648. unsigned int blk256_width = 0;
  649. unsigned int swath_bytes_horz_wc, swath_bytes_vert_wc;
  650. hubbub1_get_blk256_size(&blk256_width, &blk256_height, bpe);
  651. swath_bytes_horz_wc = height * blk256_height * bpe;
  652. swath_bytes_vert_wc = width * blk256_width * bpe;
  653. *req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ?
  654. false : /* full 256B request */
  655. true; /* half 128b request */
  656. *req128_vert_wc = (2 * swath_bytes_vert_wc <= detile_buf_size) ?
  657. false : /* full 256B request */
  658. true; /* half 128b request */
  659. }
  660. static bool hubbub1_get_dcc_compression_cap(struct hubbub *hubbub,
  661. const struct dc_dcc_surface_param *input,
  662. struct dc_surface_dcc_cap *output)
  663. {
  664. struct dc *dc = hubbub->ctx->dc;
  665. /* implement section 1.6.2.1 of DCN1_Programming_Guide.docx */
  666. enum dcc_control dcc_control;
  667. unsigned int bpe;
  668. enum segment_order segment_order_horz, segment_order_vert;
  669. bool req128_horz_wc, req128_vert_wc;
  670. memset(output, 0, sizeof(*output));
  671. if (dc->debug.disable_dcc == DCC_DISABLE)
  672. return false;
  673. if (!hubbub->funcs->dcc_support_pixel_format(input->format, &bpe))
  674. return false;
  675. if (!hubbub->funcs->dcc_support_swizzle(input->swizzle_mode, bpe,
  676. &segment_order_horz, &segment_order_vert))
  677. return false;
  678. hubbub1_det_request_size(input->surface_size.height, input->surface_size.width,
  679. bpe, &req128_horz_wc, &req128_vert_wc);
  680. if (!req128_horz_wc && !req128_vert_wc) {
  681. dcc_control = dcc_control__256_256_xxx;
  682. } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {
  683. if (!req128_horz_wc)
  684. dcc_control = dcc_control__256_256_xxx;
  685. else if (segment_order_horz == segment_order__contiguous)
  686. dcc_control = dcc_control__128_128_xxx;
  687. else
  688. dcc_control = dcc_control__256_64_64;
  689. } else if (input->scan == SCAN_DIRECTION_VERTICAL) {
  690. if (!req128_vert_wc)
  691. dcc_control = dcc_control__256_256_xxx;
  692. else if (segment_order_vert == segment_order__contiguous)
  693. dcc_control = dcc_control__128_128_xxx;
  694. else
  695. dcc_control = dcc_control__256_64_64;
  696. } else {
  697. if ((req128_horz_wc &&
  698. segment_order_horz == segment_order__non_contiguous) ||
  699. (req128_vert_wc &&
  700. segment_order_vert == segment_order__non_contiguous))
  701. /* access_dir not known, must use most constraining */
  702. dcc_control = dcc_control__256_64_64;
  703. else
  704. /* reg128 is true for either horz and vert
  705. * but segment_order is contiguous
  706. */
  707. dcc_control = dcc_control__128_128_xxx;
  708. }
  709. if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE &&
  710. dcc_control != dcc_control__256_256_xxx)
  711. return false;
  712. switch (dcc_control) {
  713. case dcc_control__256_256_xxx:
  714. output->grph.rgb.max_uncompressed_blk_size = 256;
  715. output->grph.rgb.max_compressed_blk_size = 256;
  716. output->grph.rgb.independent_64b_blks = false;
  717. break;
  718. case dcc_control__128_128_xxx:
  719. output->grph.rgb.max_uncompressed_blk_size = 128;
  720. output->grph.rgb.max_compressed_blk_size = 128;
  721. output->grph.rgb.independent_64b_blks = false;
  722. break;
  723. case dcc_control__256_64_64:
  724. output->grph.rgb.max_uncompressed_blk_size = 256;
  725. output->grph.rgb.max_compressed_blk_size = 64;
  726. output->grph.rgb.independent_64b_blks = true;
  727. break;
  728. }
  729. output->capable = true;
  730. output->const_color_support = false;
  731. return true;
  732. }
  733. static const struct hubbub_funcs hubbub1_funcs = {
  734. .update_dchub = hubbub1_update_dchub,
  735. .dcc_support_swizzle = hubbub1_dcc_support_swizzle,
  736. .dcc_support_pixel_format = hubbub1_dcc_support_pixel_format,
  737. .get_dcc_compression_cap = hubbub1_get_dcc_compression_cap,
  738. };
  739. void hubbub1_construct(struct hubbub *hubbub,
  740. struct dc_context *ctx,
  741. const struct dcn_hubbub_registers *hubbub_regs,
  742. const struct dcn_hubbub_shift *hubbub_shift,
  743. const struct dcn_hubbub_mask *hubbub_mask)
  744. {
  745. hubbub->ctx = ctx;
  746. hubbub->funcs = &hubbub1_funcs;
  747. hubbub->regs = hubbub_regs;
  748. hubbub->shifts = hubbub_shift;
  749. hubbub->masks = hubbub_mask;
  750. hubbub->debug_test_index_pstate = 0x7;
  751. #if defined(CONFIG_DRM_AMD_DC_DCN1_01)
  752. if (ctx->dce_version == DCN_VERSION_1_01)
  753. hubbub->debug_test_index_pstate = 0xB;
  754. #endif
  755. }