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