root/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. convert_and_clamp
  2. dcn21_dchvm_init
  3. hubbub21_init_dchub
  4. hubbub21_program_urgent_watermarks
  5. hubbub21_program_stutter_watermarks
  6. hubbub21_program_pstate_watermarks
  7. hubbub21_program_watermarks
  8. hubbub21_wm_read_state
  9. hubbub21_construct

   1 /*
   2 * Copyright 2018 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 <linux/delay.h>
  26 #include "dm_services.h"
  27 #include "dcn20/dcn20_hubbub.h"
  28 #include "dcn21_hubbub.h"
  29 #include "reg_helper.h"
  30 
  31 #define REG(reg)\
  32         hubbub1->regs->reg
  33 #define DC_LOGGER \
  34         hubbub1->base.ctx->logger
  35 #define CTX \
  36         hubbub1->base.ctx
  37 
  38 #undef FN
  39 #define FN(reg_name, field_name) \
  40         hubbub1->shifts->field_name, hubbub1->masks->field_name
  41 
  42 #define REG(reg)\
  43         hubbub1->regs->reg
  44 
  45 #define CTX \
  46         hubbub1->base.ctx
  47 
  48 #undef FN
  49 #define FN(reg_name, field_name) \
  50         hubbub1->shifts->field_name, hubbub1->masks->field_name
  51 
  52 #ifdef NUM_VMID
  53 #undef NUM_VMID
  54 #endif
  55 #define NUM_VMID 1
  56 
  57 static uint32_t convert_and_clamp(
  58         uint32_t wm_ns,
  59         uint32_t refclk_mhz,
  60         uint32_t clamp_value)
  61 {
  62         uint32_t ret_val = 0;
  63         ret_val = wm_ns * refclk_mhz;
  64         ret_val /= 1000;
  65 
  66         if (ret_val > clamp_value)
  67                 ret_val = clamp_value;
  68 
  69         return ret_val;
  70 }
  71 
  72 void dcn21_dchvm_init(struct hubbub *hubbub)
  73 {
  74         struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
  75         uint32_t riommu_active;
  76         int i;
  77 
  78         //Init DCHVM block
  79         REG_UPDATE(DCHVM_CTRL0, HOSTVM_INIT_REQ, 1);
  80 
  81         //Poll until RIOMMU_ACTIVE = 1
  82         for (i = 0; i < 100; i++) {
  83                 REG_GET(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, &riommu_active);
  84 
  85                 if (riommu_active)
  86                         break;
  87                 else
  88                         udelay(5);
  89         }
  90 
  91         if (riommu_active) {
  92                 //Reflect the power status of DCHUBBUB
  93                 REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, 1);
  94 
  95                 //Start rIOMMU prefetching
  96                 REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, 1);
  97 
  98                 // Enable dynamic clock gating
  99                 REG_UPDATE_4(DCHVM_CLK_CTRL,
 100                                                 HVM_DISPCLK_R_GATE_DIS, 0,
 101                                                 HVM_DISPCLK_G_GATE_DIS, 0,
 102                                                 HVM_DCFCLK_R_GATE_DIS, 0,
 103                                                 HVM_DCFCLK_G_GATE_DIS, 0);
 104 
 105                 //Poll until HOSTVM_PREFETCH_DONE = 1
 106                 REG_WAIT(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, 1, 5, 100);
 107         }
 108 }
 109 
 110 static int hubbub21_init_dchub(struct hubbub *hubbub,
 111                 struct dcn_hubbub_phys_addr_config *pa_config)
 112 {
 113         struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
 114 
 115         REG_SET(DCN_VM_FB_LOCATION_BASE, 0,
 116                 FB_BASE, pa_config->system_aperture.fb_base);
 117         REG_SET(DCN_VM_FB_LOCATION_TOP, 0,
 118                         FB_TOP, pa_config->system_aperture.fb_top);
 119         REG_SET(DCN_VM_FB_OFFSET, 0,
 120                         FB_OFFSET, pa_config->system_aperture.fb_offset);
 121         REG_SET(DCN_VM_AGP_BOT, 0,
 122                         AGP_BOT, pa_config->system_aperture.agp_bot);
 123         REG_SET(DCN_VM_AGP_TOP, 0,
 124                         AGP_TOP, pa_config->system_aperture.agp_top);
 125         REG_SET(DCN_VM_AGP_BASE, 0,
 126                         AGP_BASE, pa_config->system_aperture.agp_base);
 127 
 128         dcn21_dchvm_init(hubbub);
 129 
 130         return NUM_VMID;
 131 }
 132 
 133 static void hubbub21_program_urgent_watermarks(
 134                 struct hubbub *hubbub,
 135                 struct dcn_watermark_set *watermarks,
 136                 unsigned int refclk_mhz,
 137                 bool safe_to_lower)
 138 {
 139         struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
 140         uint32_t prog_wm_value;
 141 
 142         /* Repeat for water mark set A, B, C and D. */
 143         /* clock state A */
 144         if (safe_to_lower || watermarks->a.urgent_ns > hubbub1->watermarks.a.urgent_ns) {
 145                 hubbub1->watermarks.a.urgent_ns = watermarks->a.urgent_ns;
 146                 prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,
 147                                 refclk_mhz, 0x1fffff);
 148                 REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,
 149                                 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value,
 150                                 DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_A, prog_wm_value);
 151 
 152                 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"
 153                         "HW register value = 0x%x\n",
 154                         watermarks->a.urgent_ns, prog_wm_value);
 155         }
 156 
 157         /* determine the transfer time for a quantity of data for a particular requestor.*/
 158         if (safe_to_lower || watermarks->a.frac_urg_bw_flip
 159                         > hubbub1->watermarks.a.frac_urg_bw_flip) {
 160                 hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;
 161 
 162                 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0,
 163                                 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->a.frac_urg_bw_flip);
 164         }
 165 
 166         if (safe_to_lower || watermarks->a.frac_urg_bw_nom
 167                         > hubbub1->watermarks.a.frac_urg_bw_nom) {
 168                 hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;
 169 
 170                 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0,
 171                                 DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->a.frac_urg_bw_nom);
 172         }
 173 
 174         /* clock state B */
 175         if (safe_to_lower || watermarks->b.urgent_ns > hubbub1->watermarks.b.urgent_ns) {
 176                 hubbub1->watermarks.b.urgent_ns = watermarks->b.urgent_ns;
 177                 prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns,
 178                                 refclk_mhz, 0x1fffff);
 179                 REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0,
 180                                 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value,
 181                                 DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_B, prog_wm_value);
 182 
 183                 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"
 184                         "HW register value = 0x%x\n",
 185                         watermarks->b.urgent_ns, prog_wm_value);
 186         }
 187 
 188         /* determine the transfer time for a quantity of data for a particular requestor.*/
 189         if (safe_to_lower || watermarks->a.frac_urg_bw_flip
 190                         > hubbub1->watermarks.a.frac_urg_bw_flip) {
 191                 hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;
 192 
 193                 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0,
 194                                 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->a.frac_urg_bw_flip);
 195         }
 196 
 197         if (safe_to_lower || watermarks->a.frac_urg_bw_nom
 198                         > hubbub1->watermarks.a.frac_urg_bw_nom) {
 199                 hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;
 200 
 201                 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0,
 202                                 DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->a.frac_urg_bw_nom);
 203         }
 204 
 205         /* clock state C */
 206         if (safe_to_lower || watermarks->c.urgent_ns > hubbub1->watermarks.c.urgent_ns) {
 207                 hubbub1->watermarks.c.urgent_ns = watermarks->c.urgent_ns;
 208                 prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns,
 209                                 refclk_mhz, 0x1fffff);
 210                 REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0,
 211                                 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value,
 212                                 DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_C, prog_wm_value);
 213 
 214                 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"
 215                         "HW register value = 0x%x\n",
 216                         watermarks->c.urgent_ns, prog_wm_value);
 217         }
 218 
 219         /* determine the transfer time for a quantity of data for a particular requestor.*/
 220         if (safe_to_lower || watermarks->a.frac_urg_bw_flip
 221                         > hubbub1->watermarks.a.frac_urg_bw_flip) {
 222                 hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;
 223 
 224                 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0,
 225                                 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->a.frac_urg_bw_flip);
 226         }
 227 
 228         if (safe_to_lower || watermarks->a.frac_urg_bw_nom
 229                         > hubbub1->watermarks.a.frac_urg_bw_nom) {
 230                 hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;
 231 
 232                 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0,
 233                                 DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->a.frac_urg_bw_nom);
 234         }
 235 
 236         /* clock state D */
 237         if (safe_to_lower || watermarks->d.urgent_ns > hubbub1->watermarks.d.urgent_ns) {
 238                 hubbub1->watermarks.d.urgent_ns = watermarks->d.urgent_ns;
 239                 prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns,
 240                                 refclk_mhz, 0x1fffff);
 241                 REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0,
 242                                 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value,
 243                                 DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_D, prog_wm_value);
 244 
 245                 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"
 246                         "HW register value = 0x%x\n",
 247                         watermarks->d.urgent_ns, prog_wm_value);
 248         }
 249 
 250         /* determine the transfer time for a quantity of data for a particular requestor.*/
 251         if (safe_to_lower || watermarks->a.frac_urg_bw_flip
 252                         > hubbub1->watermarks.a.frac_urg_bw_flip) {
 253                 hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;
 254 
 255                 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0,
 256                                 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->a.frac_urg_bw_flip);
 257         }
 258 
 259         if (safe_to_lower || watermarks->a.frac_urg_bw_nom
 260                         > hubbub1->watermarks.a.frac_urg_bw_nom) {
 261                 hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;
 262 
 263                 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0,
 264                                 DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->a.frac_urg_bw_nom);
 265         }
 266 }
 267 
 268 static void hubbub21_program_stutter_watermarks(
 269                 struct hubbub *hubbub,
 270                 struct dcn_watermark_set *watermarks,
 271                 unsigned int refclk_mhz,
 272                 bool safe_to_lower)
 273 {
 274         struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
 275         uint32_t prog_wm_value;
 276 
 277         /* clock state A */
 278         if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
 279                         > hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) {
 280                 hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =
 281                                 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;
 282                 prog_wm_value = convert_and_clamp(
 283                                 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,
 284                                 refclk_mhz, 0x1fffff);
 285                 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,
 286                                 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value,
 287                                 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);
 288                 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
 289                         "HW register value = 0x%x\n",
 290                         watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
 291         }
 292 
 293         if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns
 294                         > hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) {
 295                 hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns =
 296                                 watermarks->a.cstate_pstate.cstate_exit_ns;
 297                 prog_wm_value = convert_and_clamp(
 298                                 watermarks->a.cstate_pstate.cstate_exit_ns,
 299                                 refclk_mhz, 0x1fffff);
 300                 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,
 301                                 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value,
 302                                 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
 303                 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
 304                         "HW register value = 0x%x\n",
 305                         watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);
 306         }
 307 
 308         /* clock state B */
 309         if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
 310                         > hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) {
 311                 hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns =
 312                                 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;
 313                 prog_wm_value = convert_and_clamp(
 314                                 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,
 315                                 refclk_mhz, 0x1fffff);
 316                 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,
 317                                 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value,
 318                                 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);
 319                 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"
 320                         "HW register value = 0x%x\n",
 321                         watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
 322         }
 323 
 324         if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns
 325                         > hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) {
 326                 hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns =
 327                                 watermarks->b.cstate_pstate.cstate_exit_ns;
 328                 prog_wm_value = convert_and_clamp(
 329                                 watermarks->b.cstate_pstate.cstate_exit_ns,
 330                                 refclk_mhz, 0x1fffff);
 331                 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,
 332                                 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value,
 333                                 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
 334                 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
 335                         "HW register value = 0x%x\n",
 336                         watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);
 337         }
 338 
 339         /* clock state C */
 340         if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
 341                         > hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) {
 342                 hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns =
 343                                 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;
 344                 prog_wm_value = convert_and_clamp(
 345                                 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,
 346                                 refclk_mhz, 0x1fffff);
 347                 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0,
 348                                 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value,
 349                                 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);
 350                 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"
 351                         "HW register value = 0x%x\n",
 352                         watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
 353         }
 354 
 355         if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns
 356                         > hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) {
 357                 hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns =
 358                                 watermarks->c.cstate_pstate.cstate_exit_ns;
 359                 prog_wm_value = convert_and_clamp(
 360                                 watermarks->c.cstate_pstate.cstate_exit_ns,
 361                                 refclk_mhz, 0x1fffff);
 362                 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0,
 363                                 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value,
 364                                 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
 365                 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
 366                         "HW register value = 0x%x\n",
 367                         watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);
 368         }
 369 
 370         /* clock state D */
 371         if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
 372                         > hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) {
 373                 hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns =
 374                                 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;
 375                 prog_wm_value = convert_and_clamp(
 376                                 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,
 377                                 refclk_mhz, 0x1fffff);
 378                 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0,
 379                                 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value,
 380                                 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);
 381                 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"
 382                         "HW register value = 0x%x\n",
 383                         watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
 384         }
 385 
 386         if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns
 387                         > hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) {
 388                 hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns =
 389                                 watermarks->d.cstate_pstate.cstate_exit_ns;
 390                 prog_wm_value = convert_and_clamp(
 391                                 watermarks->d.cstate_pstate.cstate_exit_ns,
 392                                 refclk_mhz, 0x1fffff);
 393                 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0,
 394                                 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value,
 395                                 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
 396                 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
 397                         "HW register value = 0x%x\n",
 398                         watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);
 399         }
 400 }
 401 
 402 static void hubbub21_program_pstate_watermarks(
 403                 struct hubbub *hubbub,
 404                 struct dcn_watermark_set *watermarks,
 405                 unsigned int refclk_mhz,
 406                 bool safe_to_lower)
 407 {
 408         struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
 409         uint32_t prog_wm_value;
 410 
 411         /* clock state A */
 412         if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns
 413                         > hubbub1->watermarks.a.cstate_pstate.pstate_change_ns) {
 414                 hubbub1->watermarks.a.cstate_pstate.pstate_change_ns =
 415                                 watermarks->a.cstate_pstate.pstate_change_ns;
 416                 prog_wm_value = convert_and_clamp(
 417                                 watermarks->a.cstate_pstate.pstate_change_ns,
 418                                 refclk_mhz, 0x1fffff);
 419                 REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, 0,
 420                                 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value,
 421                                 DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value);
 422                 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
 423                         "HW register value = 0x%x\n\n",
 424                         watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);
 425         }
 426 
 427         /* clock state B */
 428         if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns
 429                         > hubbub1->watermarks.b.cstate_pstate.pstate_change_ns) {
 430                 hubbub1->watermarks.b.cstate_pstate.pstate_change_ns =
 431                                 watermarks->b.cstate_pstate.pstate_change_ns;
 432                 prog_wm_value = convert_and_clamp(
 433                                 watermarks->b.cstate_pstate.pstate_change_ns,
 434                                 refclk_mhz, 0x1fffff);
 435                 REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, 0,
 436                                 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value,
 437                                 DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value);
 438                 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"
 439                         "HW register value = 0x%x\n\n",
 440                         watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);
 441         }
 442 
 443         /* clock state C */
 444         if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns
 445                         > hubbub1->watermarks.c.cstate_pstate.pstate_change_ns) {
 446                 hubbub1->watermarks.c.cstate_pstate.pstate_change_ns =
 447                                 watermarks->c.cstate_pstate.pstate_change_ns;
 448                 prog_wm_value = convert_and_clamp(
 449                                 watermarks->c.cstate_pstate.pstate_change_ns,
 450                                 refclk_mhz, 0x1fffff);
 451                 REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, 0,
 452                                 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value,
 453                                 DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value);
 454                 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"
 455                         "HW register value = 0x%x\n\n",
 456                         watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);
 457         }
 458 
 459         /* clock state D */
 460         if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns
 461                         > hubbub1->watermarks.d.cstate_pstate.pstate_change_ns) {
 462                 hubbub1->watermarks.d.cstate_pstate.pstate_change_ns =
 463                                 watermarks->d.cstate_pstate.pstate_change_ns;
 464                 prog_wm_value = convert_and_clamp(
 465                                 watermarks->d.cstate_pstate.pstate_change_ns,
 466                                 refclk_mhz, 0x1fffff);
 467                 REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, 0,
 468                                 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value,
 469                                 DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value);
 470                 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
 471                         "HW register value = 0x%x\n\n",
 472                         watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);
 473         }
 474 }
 475 
 476 void hubbub21_program_watermarks(
 477                 struct hubbub *hubbub,
 478                 struct dcn_watermark_set *watermarks,
 479                 unsigned int refclk_mhz,
 480                 bool safe_to_lower)
 481 {
 482         struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
 483 
 484         hubbub21_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
 485         hubbub21_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
 486         hubbub21_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
 487 
 488         /*
 489          * The DCHub arbiter has a mechanism to dynamically rate limit the DCHub request stream to the fabric.
 490          * If the memory controller is fully utilized and the DCHub requestors are
 491          * well ahead of their amortized schedule, then it is safe to prevent the next winner
 492          * from being committed and sent to the fabric.
 493          * The utilization of the memory controller is approximated by ensuring that
 494          * the number of outstanding requests is greater than a threshold specified
 495          * by the ARB_MIN_REQ_OUTSTANDING. To determine that the DCHub requestors are well ahead of the amortized schedule,
 496          * the slack of the next winner is compared with the ARB_SAT_LEVEL in DLG RefClk cycles.
 497          *
 498          * TODO: Revisit request limit after figure out right number. request limit for Renoir isn't decided yet, set maximum value (0x1FF)
 499          * to turn off it for now.
 500          */
 501         REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,
 502                         DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
 503         REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
 504                         DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF,
 505                         DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);
 506         REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL,
 507                         DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF);
 508 
 509         hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
 510 }
 511 
 512 void hubbub21_wm_read_state(struct hubbub *hubbub,
 513                 struct dcn_hubbub_wm *wm)
 514 {
 515         struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
 516         struct dcn_hubbub_wm_set *s;
 517 
 518         memset(wm, 0, sizeof(struct dcn_hubbub_wm));
 519 
 520         s = &wm->sets[0];
 521         s->wm_set = 0;
 522         REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A,
 523                         DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, &s->data_urgent);
 524 
 525         REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A,
 526                         DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, &s->sr_enter);
 527 
 528         REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A,
 529                         DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit);
 530 
 531         REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A,
 532                          DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, &s->dram_clk_chanage);
 533 
 534         s = &wm->sets[1];
 535         s->wm_set = 1;
 536         REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B,
 537                         DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, &s->data_urgent);
 538 
 539         REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B,
 540                         DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, &s->sr_enter);
 541 
 542         REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B,
 543                         DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit);
 544 
 545         REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B,
 546                         DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, &s->dram_clk_chanage);
 547 
 548         s = &wm->sets[2];
 549         s->wm_set = 2;
 550         REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C,
 551                         DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, &s->data_urgent);
 552 
 553         REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C,
 554                         DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, &s->sr_enter);
 555 
 556         REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C,
 557                         DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, &s->sr_exit);
 558 
 559         REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C,
 560                         DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, &s->dram_clk_chanage);
 561 
 562         s = &wm->sets[3];
 563         s->wm_set = 3;
 564         REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D,
 565                         DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, &s->data_urgent);
 566 
 567         REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D,
 568                         DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, &s->sr_enter);
 569 
 570         REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D,
 571                         DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, &s->sr_exit);
 572 
 573         REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D,
 574                         DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, &s->dram_clk_chanage);
 575 }
 576 
 577 
 578 static const struct hubbub_funcs hubbub21_funcs = {
 579         .update_dchub = hubbub2_update_dchub,
 580         .init_dchub_sys_ctx = hubbub21_init_dchub,
 581         .init_vm_ctx = NULL,
 582         .dcc_support_swizzle = hubbub2_dcc_support_swizzle,
 583         .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,
 584         .get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,
 585         .wm_read_state = hubbub21_wm_read_state,
 586         .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
 587         .program_watermarks = hubbub21_program_watermarks,
 588 };
 589 
 590 void hubbub21_construct(struct dcn20_hubbub *hubbub,
 591         struct dc_context *ctx,
 592         const struct dcn_hubbub_registers *hubbub_regs,
 593         const struct dcn_hubbub_shift *hubbub_shift,
 594         const struct dcn_hubbub_mask *hubbub_mask)
 595 {
 596         hubbub->base.ctx = ctx;
 597 
 598         hubbub->base.funcs = &hubbub21_funcs;
 599 
 600         hubbub->regs = hubbub_regs;
 601         hubbub->shifts = hubbub_shift;
 602         hubbub->masks = hubbub_mask;
 603 
 604         hubbub->debug_test_index_pstate = 0xB;
 605 }

/* [<][>][^][v][top][bottom][index][help] */