linux/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012-15 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#include <linux/slab.h>
  28
  29#include "dm_services.h"
  30
  31#include "dce/dce_11_2_d.h"
  32#include "dce/dce_11_2_sh_mask.h"
  33#include "gmc/gmc_8_1_sh_mask.h"
  34#include "gmc/gmc_8_1_d.h"
  35
  36#include "include/logger_interface.h"
  37
  38#include "dce112_compressor.h"
  39#define DC_LOGGER \
  40                cp110->base.ctx->logger
  41#define DCP_REG(reg)\
  42        (reg + cp110->offsets.dcp_offset)
  43#define DMIF_REG(reg)\
  44        (reg + cp110->offsets.dmif_offset)
  45
  46static const struct dce112_compressor_reg_offsets reg_offsets[] = {
  47{
  48        .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
  49        .dmif_offset =
  50                (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
  51                        - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
  52},
  53{
  54        .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
  55        .dmif_offset =
  56                (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL
  57                        - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
  58},
  59{
  60        .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
  61        .dmif_offset =
  62                (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL
  63                        - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
  64}
  65};
  66
  67static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600;
  68
  69enum fbc_idle_force {
  70        /* Bit 0 - Display registers updated */
  71        FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001,
  72
  73        /* Bit 2 - FBC_GRPH_COMP_EN register updated */
  74        FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002,
  75        /* Bit 3 - FBC_SRC_SEL register updated */
  76        FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004,
  77        /* Bit 4 - FBC_MIN_COMPRESSION register updated */
  78        FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008,
  79        /* Bit 5 - FBC_ALPHA_COMP_EN register updated */
  80        FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010,
  81        /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */
  82        FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020,
  83        /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */
  84        FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040,
  85
  86        /* Bit 24 - Memory write to region 0 defined by MC registers. */
  87        FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000,
  88        /* Bit 25 - Memory write to region 1 defined by MC registers */
  89        FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000,
  90        /* Bit 26 - Memory write to region 2 defined by MC registers */
  91        FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000,
  92        /* Bit 27 - Memory write to region 3 defined by MC registers. */
  93        FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000,
  94
  95        /* Bit 28 - Memory write from any client other than MCIF */
  96        FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000,
  97        /* Bit 29 - CG statics screen signal is inactive */
  98        FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000,
  99};
 100
 101static uint32_t lpt_size_alignment(struct dce112_compressor *cp110)
 102{
 103        /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */
 104        return cp110->base.raw_size * cp110->base.banks_num *
 105                cp110->base.dram_channels_num;
 106}
 107
 108static uint32_t lpt_memory_control_config(struct dce112_compressor *cp110,
 109        uint32_t lpt_control)
 110{
 111        /*LPT MC Config */
 112        if (cp110->base.options.bits.LPT_MC_CONFIG == 1) {
 113                /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS):
 114                 * 00 - 1 CHANNEL
 115                 * 01 - 2 CHANNELS
 116                 * 02 - 4 OR 6 CHANNELS
 117                 * (Only for discrete GPU, N/A for CZ)
 118                 * 03 - 8 OR 12 CHANNELS
 119                 * (Only for discrete GPU, N/A for CZ) */
 120                switch (cp110->base.dram_channels_num) {
 121                case 2:
 122                        set_reg_field_value(
 123                                lpt_control,
 124                                1,
 125                                LOW_POWER_TILING_CONTROL,
 126                                LOW_POWER_TILING_NUM_PIPES);
 127                        break;
 128                case 1:
 129                        set_reg_field_value(
 130                                lpt_control,
 131                                0,
 132                                LOW_POWER_TILING_CONTROL,
 133                                LOW_POWER_TILING_NUM_PIPES);
 134                        break;
 135                default:
 136                        DC_LOG_WARNING(
 137                                "%s: Invalid LPT NUM_PIPES!!!",
 138                                __func__);
 139                        break;
 140                }
 141
 142                /* The mapping for LPT NUM_BANKS is in
 143                 * GRPH_CONTROL.GRPH_NUM_BANKS register field
 144                 * Specifies the number of memory banks for tiling
 145                 * purposes. Only applies to 2D and 3D tiling modes.
 146                 * POSSIBLE VALUES:
 147                 * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK
 148                 * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK
 149                 * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK
 150                 * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */
 151                switch (cp110->base.banks_num) {
 152                case 16:
 153                        set_reg_field_value(
 154                                lpt_control,
 155                                3,
 156                                LOW_POWER_TILING_CONTROL,
 157                                LOW_POWER_TILING_NUM_BANKS);
 158                        break;
 159                case 8:
 160                        set_reg_field_value(
 161                                lpt_control,
 162                                2,
 163                                LOW_POWER_TILING_CONTROL,
 164                                LOW_POWER_TILING_NUM_BANKS);
 165                        break;
 166                case 4:
 167                        set_reg_field_value(
 168                                lpt_control,
 169                                1,
 170                                LOW_POWER_TILING_CONTROL,
 171                                LOW_POWER_TILING_NUM_BANKS);
 172                        break;
 173                case 2:
 174                        set_reg_field_value(
 175                                lpt_control,
 176                                0,
 177                                LOW_POWER_TILING_CONTROL,
 178                                LOW_POWER_TILING_NUM_BANKS);
 179                        break;
 180                default:
 181                        DC_LOG_WARNING(
 182                                "%s: Invalid LPT NUM_BANKS!!!",
 183                                __func__);
 184                        break;
 185                }
 186
 187                /* The mapping is in DMIF_ADDR_CALC.
 188                 * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for
 189                 * Carrizo specifies the memory interleave per pipe.
 190                 * It effectively specifies the location of pipe bits in
 191                 * the memory address.
 192                 * POSSIBLE VALUES:
 193                 * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte
 194                 * interleave
 195                 * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte
 196                 * interleave
 197                 */
 198                switch (cp110->base.channel_interleave_size) {
 199                case 256: /*256B */
 200                        set_reg_field_value(
 201                                lpt_control,
 202                                0,
 203                                LOW_POWER_TILING_CONTROL,
 204                                LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE);
 205                        break;
 206                case 512: /*512B */
 207                        set_reg_field_value(
 208                                lpt_control,
 209                                1,
 210                                LOW_POWER_TILING_CONTROL,
 211                                LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE);
 212                        break;
 213                default:
 214                        DC_LOG_WARNING(
 215                                "%s: Invalid LPT INTERLEAVE_SIZE!!!",
 216                                __func__);
 217                        break;
 218                }
 219
 220                /* The mapping for LOW_POWER_TILING_ROW_SIZE is in
 221                 * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field
 222                 * for Carrizo. Specifies the size of dram row in bytes.
 223                 * This should match up with NOOFCOLS field in
 224                 * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns).
 225                 * This register DMIF_ADDR_CALC is not used by the
 226                 * hardware as it is only used for addrlib assertions.
 227                 * POSSIBLE VALUES:
 228                 * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row
 229                 * boundary
 230                 * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row
 231                 * boundary
 232                 * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row
 233                 * boundary */
 234                switch (cp110->base.raw_size) {
 235                case 4096: /*4 KB */
 236                        set_reg_field_value(
 237                                lpt_control,
 238                                2,
 239                                LOW_POWER_TILING_CONTROL,
 240                                LOW_POWER_TILING_ROW_SIZE);
 241                        break;
 242                case 2048:
 243                        set_reg_field_value(
 244                                lpt_control,
 245                                1,
 246                                LOW_POWER_TILING_CONTROL,
 247                                LOW_POWER_TILING_ROW_SIZE);
 248                        break;
 249                case 1024:
 250                        set_reg_field_value(
 251                                lpt_control,
 252                                0,
 253                                LOW_POWER_TILING_CONTROL,
 254                                LOW_POWER_TILING_ROW_SIZE);
 255                        break;
 256                default:
 257                        DC_LOG_WARNING(
 258                                "%s: Invalid LPT ROW_SIZE!!!",
 259                                __func__);
 260                        break;
 261                }
 262        } else {
 263                DC_LOG_WARNING(
 264                        "%s: LPT MC Configuration is not provided",
 265                        __func__);
 266        }
 267
 268        return lpt_control;
 269}
 270
 271static bool is_source_bigger_than_epanel_size(
 272        struct dce112_compressor *cp110,
 273        uint32_t source_view_width,
 274        uint32_t source_view_height)
 275{
 276        if (cp110->base.embedded_panel_h_size != 0 &&
 277                cp110->base.embedded_panel_v_size != 0 &&
 278                ((source_view_width * source_view_height) >
 279                (cp110->base.embedded_panel_h_size *
 280                        cp110->base.embedded_panel_v_size)))
 281                return true;
 282
 283        return false;
 284}
 285
 286static uint32_t align_to_chunks_number_per_line(
 287        struct dce112_compressor *cp110,
 288        uint32_t pixels)
 289{
 290        return 256 * ((pixels + 255) / 256);
 291}
 292
 293static void wait_for_fbc_state_changed(
 294        struct dce112_compressor *cp110,
 295        bool enabled)
 296{
 297        uint8_t counter = 0;
 298        uint32_t addr = mmFBC_STATUS;
 299        uint32_t value;
 300
 301        while (counter < 10) {
 302                value = dm_read_reg(cp110->base.ctx, addr);
 303                if (get_reg_field_value(
 304                        value,
 305                        FBC_STATUS,
 306                        FBC_ENABLE_STATUS) == enabled)
 307                        break;
 308                udelay(10);
 309                counter++;
 310        }
 311
 312        if (counter == 10) {
 313                DC_LOG_WARNING(
 314                        "%s: wait counter exceeded, changes to HW not applied",
 315                        __func__);
 316        }
 317}
 318
 319void dce112_compressor_power_up_fbc(struct compressor *compressor)
 320{
 321        uint32_t value;
 322        uint32_t addr;
 323
 324        addr = mmFBC_CNTL;
 325        value = dm_read_reg(compressor->ctx, addr);
 326        set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
 327        set_reg_field_value(value, 1, FBC_CNTL, FBC_EN);
 328        set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE);
 329        if (compressor->options.bits.CLK_GATING_DISABLED == 1) {
 330                /* HW needs to do power measurement comparison. */
 331                set_reg_field_value(
 332                        value,
 333                        0,
 334                        FBC_CNTL,
 335                        FBC_COMP_CLK_GATE_EN);
 336        }
 337        dm_write_reg(compressor->ctx, addr, value);
 338
 339        addr = mmFBC_COMP_MODE;
 340        value = dm_read_reg(compressor->ctx, addr);
 341        set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN);
 342        set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN);
 343        set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN);
 344        dm_write_reg(compressor->ctx, addr, value);
 345
 346        addr = mmFBC_COMP_CNTL;
 347        value = dm_read_reg(compressor->ctx, addr);
 348        set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN);
 349        dm_write_reg(compressor->ctx, addr, value);
 350        /*FBC_MIN_COMPRESSION 0 ==> 2:1 */
 351        /*                    1 ==> 4:1 */
 352        /*                    2 ==> 8:1 */
 353        /*                  0xF ==> 1:1 */
 354        set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION);
 355        dm_write_reg(compressor->ctx, addr, value);
 356        compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1;
 357
 358        value = 0;
 359        dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value);
 360
 361        value = 0xFFFFFF;
 362        dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value);
 363}
 364
 365void dce112_compressor_enable_fbc(
 366        struct compressor *compressor,
 367        uint32_t paths_num,
 368        struct compr_addr_and_pitch_params *params)
 369{
 370        struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
 371
 372        if (compressor->options.bits.FBC_SUPPORT &&
 373                (compressor->options.bits.DUMMY_BACKEND == 0) &&
 374                (!dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) &&
 375                (!is_source_bigger_than_epanel_size(
 376                        cp110,
 377                        params->source_view_width,
 378                        params->source_view_height))) {
 379
 380                uint32_t addr;
 381                uint32_t value;
 382
 383                /* Before enabling FBC first need to enable LPT if applicable
 384                 * LPT state should always be changed (enable/disable) while FBC
 385                 * is disabled */
 386                if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) &&
 387                        (params->source_view_width *
 388                                params->source_view_height <=
 389                                dce11_one_lpt_channel_max_resolution)) {
 390                        dce112_compressor_enable_lpt(compressor);
 391                }
 392
 393                addr = mmFBC_CNTL;
 394                value = dm_read_reg(compressor->ctx, addr);
 395                set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
 396                set_reg_field_value(
 397                        value,
 398                        params->inst,
 399                        FBC_CNTL, FBC_SRC_SEL);
 400                dm_write_reg(compressor->ctx, addr, value);
 401
 402                /* Keep track of enum controller_id FBC is attached to */
 403                compressor->is_enabled = true;
 404                compressor->attached_inst = params->inst;
 405                cp110->offsets = reg_offsets[params->inst];
 406
 407                /*Toggle it as there is bug in HW */
 408                set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
 409                dm_write_reg(compressor->ctx, addr, value);
 410                set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
 411                dm_write_reg(compressor->ctx, addr, value);
 412
 413                wait_for_fbc_state_changed(cp110, true);
 414        }
 415}
 416
 417void dce112_compressor_disable_fbc(struct compressor *compressor)
 418{
 419        struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
 420
 421        if (compressor->options.bits.FBC_SUPPORT &&
 422                dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) {
 423                uint32_t reg_data;
 424                /* Turn off compression */
 425                reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL);
 426                set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
 427                dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data);
 428
 429                /* Reset enum controller_id to undefined */
 430                compressor->attached_inst = 0;
 431                compressor->is_enabled = false;
 432
 433                /* Whenever disabling FBC make sure LPT is disabled if LPT
 434                 * supported */
 435                if (compressor->options.bits.LPT_SUPPORT)
 436                        dce112_compressor_disable_lpt(compressor);
 437
 438                wait_for_fbc_state_changed(cp110, false);
 439        }
 440}
 441
 442bool dce112_compressor_is_fbc_enabled_in_hw(
 443        struct compressor *compressor,
 444        uint32_t *inst)
 445{
 446        /* Check the hardware register */
 447        uint32_t value;
 448
 449        value = dm_read_reg(compressor->ctx, mmFBC_STATUS);
 450        if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) {
 451                if (inst != NULL)
 452                        *inst = compressor->attached_inst;
 453                return true;
 454        }
 455
 456        value = dm_read_reg(compressor->ctx, mmFBC_MISC);
 457        if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) {
 458                value = dm_read_reg(compressor->ctx, mmFBC_CNTL);
 459
 460                if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) {
 461                        if (inst != NULL)
 462                                *inst =
 463                                        compressor->attached_inst;
 464                        return true;
 465                }
 466        }
 467        return false;
 468}
 469
 470bool dce112_compressor_is_lpt_enabled_in_hw(struct compressor *compressor)
 471{
 472        /* Check the hardware register */
 473        uint32_t value = dm_read_reg(compressor->ctx,
 474                mmLOW_POWER_TILING_CONTROL);
 475
 476        return get_reg_field_value(
 477                value,
 478                LOW_POWER_TILING_CONTROL,
 479                LOW_POWER_TILING_ENABLE);
 480}
 481
 482void dce112_compressor_program_compressed_surface_address_and_pitch(
 483        struct compressor *compressor,
 484        struct compr_addr_and_pitch_params *params)
 485{
 486        struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
 487        uint32_t value = 0;
 488        uint32_t fbc_pitch = 0;
 489        uint32_t compressed_surf_address_low_part =
 490                compressor->compr_surface_address.addr.low_part;
 491
 492        /* Clear content first. */
 493        dm_write_reg(
 494                compressor->ctx,
 495                DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
 496                0);
 497        dm_write_reg(compressor->ctx,
 498                DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0);
 499
 500        if (compressor->options.bits.LPT_SUPPORT) {
 501                uint32_t lpt_alignment = lpt_size_alignment(cp110);
 502
 503                if (lpt_alignment != 0) {
 504                        compressed_surf_address_low_part =
 505                                ((compressed_surf_address_low_part
 506                                        + (lpt_alignment - 1)) / lpt_alignment)
 507                                        * lpt_alignment;
 508                }
 509        }
 510
 511        /* Write address, HIGH has to be first. */
 512        dm_write_reg(compressor->ctx,
 513                DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
 514                compressor->compr_surface_address.addr.high_part);
 515        dm_write_reg(compressor->ctx,
 516                DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS),
 517                compressed_surf_address_low_part);
 518
 519        fbc_pitch = align_to_chunks_number_per_line(
 520                cp110,
 521                params->source_view_width);
 522
 523        if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1)
 524                fbc_pitch = fbc_pitch / 8;
 525        else
 526                DC_LOG_WARNING(
 527                        "%s: Unexpected DCE11 compression ratio",
 528                        __func__);
 529
 530        /* Clear content first. */
 531        dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0);
 532
 533        /* Write FBC Pitch. */
 534        set_reg_field_value(
 535                value,
 536                fbc_pitch,
 537                GRPH_COMPRESS_PITCH,
 538                GRPH_COMPRESS_PITCH);
 539        dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value);
 540
 541}
 542
 543void dce112_compressor_disable_lpt(struct compressor *compressor)
 544{
 545        struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
 546        uint32_t value;
 547        uint32_t addr;
 548        uint32_t inx;
 549
 550        /* Disable all pipes LPT Stutter */
 551        for (inx = 0; inx < 3; inx++) {
 552                value =
 553                        dm_read_reg(
 554                                compressor->ctx,
 555                                DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH));
 556                set_reg_field_value(
 557                        value,
 558                        0,
 559                        DPG_PIPE_STUTTER_CONTROL_NONLPTCH,
 560                        STUTTER_ENABLE_NONLPTCH);
 561                dm_write_reg(
 562                        compressor->ctx,
 563                        DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH),
 564                        value);
 565        }
 566        /* Disable Underlay pipe LPT Stutter */
 567        addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH;
 568        value = dm_read_reg(compressor->ctx, addr);
 569        set_reg_field_value(
 570                value,
 571                0,
 572                DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH,
 573                STUTTER_ENABLE_NONLPTCH);
 574        dm_write_reg(compressor->ctx, addr, value);
 575
 576        /* Disable LPT */
 577        addr = mmLOW_POWER_TILING_CONTROL;
 578        value = dm_read_reg(compressor->ctx, addr);
 579        set_reg_field_value(
 580                value,
 581                0,
 582                LOW_POWER_TILING_CONTROL,
 583                LOW_POWER_TILING_ENABLE);
 584        dm_write_reg(compressor->ctx, addr, value);
 585
 586        /* Clear selection of Channel(s) containing Compressed Surface */
 587        addr = mmGMCON_LPT_TARGET;
 588        value = dm_read_reg(compressor->ctx, addr);
 589        set_reg_field_value(
 590                value,
 591                0xFFFFFFFF,
 592                GMCON_LPT_TARGET,
 593                STCTRL_LPT_TARGET);
 594        dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value);
 595}
 596
 597void dce112_compressor_enable_lpt(struct compressor *compressor)
 598{
 599        struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
 600        uint32_t value;
 601        uint32_t addr;
 602        uint32_t value_control;
 603        uint32_t channels;
 604
 605        /* Enable LPT Stutter from Display pipe */
 606        value = dm_read_reg(compressor->ctx,
 607                DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH));
 608        set_reg_field_value(
 609                value,
 610                1,
 611                DPG_PIPE_STUTTER_CONTROL_NONLPTCH,
 612                STUTTER_ENABLE_NONLPTCH);
 613        dm_write_reg(compressor->ctx,
 614                DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value);
 615
 616        /* Enable Underlay pipe LPT Stutter */
 617        addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH;
 618        value = dm_read_reg(compressor->ctx, addr);
 619        set_reg_field_value(
 620                value,
 621                1,
 622                DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH,
 623                STUTTER_ENABLE_NONLPTCH);
 624        dm_write_reg(compressor->ctx, addr, value);
 625
 626        /* Selection of Channel(s) containing Compressed Surface: 0xfffffff
 627         * will disable LPT.
 628         * STCTRL_LPT_TARGETn corresponds to channel n. */
 629        addr = mmLOW_POWER_TILING_CONTROL;
 630        value_control = dm_read_reg(compressor->ctx, addr);
 631        channels = get_reg_field_value(value_control,
 632                        LOW_POWER_TILING_CONTROL,
 633                        LOW_POWER_TILING_MODE);
 634
 635        addr = mmGMCON_LPT_TARGET;
 636        value = dm_read_reg(compressor->ctx, addr);
 637        set_reg_field_value(
 638                value,
 639                channels + 1, /* not mentioned in programming guide,
 640                                but follow DCE8.1 */
 641                GMCON_LPT_TARGET,
 642                STCTRL_LPT_TARGET);
 643        dm_write_reg(compressor->ctx, addr, value);
 644
 645        /* Enable LPT */
 646        addr = mmLOW_POWER_TILING_CONTROL;
 647        value = dm_read_reg(compressor->ctx, addr);
 648        set_reg_field_value(
 649                value,
 650                1,
 651                LOW_POWER_TILING_CONTROL,
 652                LOW_POWER_TILING_ENABLE);
 653        dm_write_reg(compressor->ctx, addr, value);
 654}
 655
 656void dce112_compressor_program_lpt_control(
 657        struct compressor *compressor,
 658        struct compr_addr_and_pitch_params *params)
 659{
 660        struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
 661        uint32_t rows_per_channel;
 662        uint32_t lpt_alignment;
 663        uint32_t source_view_width;
 664        uint32_t source_view_height;
 665        uint32_t lpt_control = 0;
 666
 667        if (!compressor->options.bits.LPT_SUPPORT)
 668                return;
 669
 670        lpt_control = dm_read_reg(compressor->ctx,
 671                mmLOW_POWER_TILING_CONTROL);
 672
 673        /* POSSIBLE VALUES for Low Power Tiling Mode:
 674         * 00 - Use channel 0
 675         * 01 - Use Channel 0 and 1
 676         * 02 - Use Channel 0,1,2,3
 677         * 03 - reserved */
 678        switch (compressor->lpt_channels_num) {
 679        /* case 2:
 680         * Use Channel 0 & 1 / Not used for DCE 11 */
 681        case 1:
 682                /*Use Channel 0 for LPT for DCE 11 */
 683                set_reg_field_value(
 684                        lpt_control,
 685                        0,
 686                        LOW_POWER_TILING_CONTROL,
 687                        LOW_POWER_TILING_MODE);
 688                break;
 689        default:
 690                DC_LOG_WARNING(
 691                        "%s: Invalid selected DRAM channels for LPT!!!",
 692                        __func__);
 693                break;
 694        }
 695
 696        lpt_control = lpt_memory_control_config(cp110, lpt_control);
 697
 698        /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on
 699         * FBC compressed surface pitch.
 700         * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height *
 701         * Surface Pitch) / (Row Size * Number of Channels *
 702         * Number of Banks)). */
 703        rows_per_channel = 0;
 704        lpt_alignment = lpt_size_alignment(cp110);
 705        source_view_width =
 706                align_to_chunks_number_per_line(
 707                        cp110,
 708                        params->source_view_width);
 709        source_view_height = (params->source_view_height + 1) & (~0x1);
 710
 711        if (lpt_alignment != 0) {
 712                rows_per_channel = source_view_width * source_view_height * 4;
 713                rows_per_channel =
 714                        (rows_per_channel % lpt_alignment) ?
 715                                (rows_per_channel / lpt_alignment + 1) :
 716                                rows_per_channel / lpt_alignment;
 717        }
 718
 719        set_reg_field_value(
 720                lpt_control,
 721                rows_per_channel,
 722                LOW_POWER_TILING_CONTROL,
 723                LOW_POWER_TILING_ROWS_PER_CHAN);
 724
 725        dm_write_reg(compressor->ctx,
 726                mmLOW_POWER_TILING_CONTROL, lpt_control);
 727}
 728
 729/*
 730 * DCE 11 Frame Buffer Compression Implementation
 731 */
 732
 733void dce112_compressor_set_fbc_invalidation_triggers(
 734        struct compressor *compressor,
 735        uint32_t fbc_trigger)
 736{
 737        /* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19)
 738         * for DCE 11 regions cannot be used - does not work with S/G
 739         */
 740        uint32_t addr = mmFBC_CLIENT_REGION_MASK;
 741        uint32_t value = dm_read_reg(compressor->ctx, addr);
 742
 743        set_reg_field_value(
 744                value,
 745                0,
 746                FBC_CLIENT_REGION_MASK,
 747                FBC_MEMORY_REGION_MASK);
 748        dm_write_reg(compressor->ctx, addr, value);
 749
 750        /* Setup events when to clear all CSM entries (effectively marking
 751         * current compressed data invalid)
 752         * For DCE 11 CSM metadata 11111 means - "Not Compressed"
 753         * Used as the initial value of the metadata sent to the compressor
 754         * after invalidation, to indicate that the compressor should attempt
 755         * to compress all chunks on the current pass.  Also used when the chunk
 756         * is not successfully written to memory.
 757         * When this CSM value is detected, FBC reads from the uncompressed
 758         * buffer. Set events according to passed in value, these events are
 759         * valid for DCE11:
 760         *     - bit  0 - display register updated
 761         *     - bit 28 - memory write from any client except from MCIF
 762         *     - bit 29 - CG static screen signal is inactive
 763         * In addition, DCE11.1 also needs to set new DCE11.1 specific events
 764         * that are used to trigger invalidation on certain register changes,
 765         * for example enabling of Alpha Compression may trigger invalidation of
 766         * FBC once bit is set. These events are as follows:
 767         *      - Bit 2 - FBC_GRPH_COMP_EN register updated
 768         *      - Bit 3 - FBC_SRC_SEL register updated
 769         *      - Bit 4 - FBC_MIN_COMPRESSION register updated
 770         *      - Bit 5 - FBC_ALPHA_COMP_EN register updated
 771         *      - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated
 772         *      - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated
 773         */
 774        addr = mmFBC_IDLE_FORCE_CLEAR_MASK;
 775        value = dm_read_reg(compressor->ctx, addr);
 776        set_reg_field_value(
 777                value,
 778                fbc_trigger |
 779                FBC_IDLE_FORCE_GRPH_COMP_EN |
 780                FBC_IDLE_FORCE_SRC_SEL_CHANGE |
 781                FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE |
 782                FBC_IDLE_FORCE_ALPHA_COMP_EN |
 783                FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN |
 784                FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF,
 785                FBC_IDLE_FORCE_CLEAR_MASK,
 786                FBC_IDLE_FORCE_CLEAR_MASK);
 787        dm_write_reg(compressor->ctx, addr, value);
 788}
 789
 790void dce112_compressor_construct(struct dce112_compressor *compressor,
 791        struct dc_context *ctx)
 792{
 793        struct dc_bios *bp = ctx->dc_bios;
 794        struct embedded_panel_info panel_info;
 795
 796        compressor->base.options.raw = 0;
 797        compressor->base.options.bits.FBC_SUPPORT = true;
 798        compressor->base.options.bits.LPT_SUPPORT = true;
 799         /* For DCE 11 always use one DRAM channel for LPT */
 800        compressor->base.lpt_channels_num = 1;
 801        compressor->base.options.bits.DUMMY_BACKEND = false;
 802
 803        /* Check if this system has more than 1 DRAM channel; if only 1 then LPT
 804         * should not be supported */
 805        if (compressor->base.memory_bus_width == 64)
 806                compressor->base.options.bits.LPT_SUPPORT = false;
 807
 808        compressor->base.options.bits.CLK_GATING_DISABLED = false;
 809
 810        compressor->base.ctx = ctx;
 811        compressor->base.embedded_panel_h_size = 0;
 812        compressor->base.embedded_panel_v_size = 0;
 813        compressor->base.memory_bus_width = ctx->asic_id.vram_width;
 814        compressor->base.allocated_size = 0;
 815        compressor->base.preferred_requested_size = 0;
 816        compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID;
 817        compressor->base.banks_num = 0;
 818        compressor->base.raw_size = 0;
 819        compressor->base.channel_interleave_size = 0;
 820        compressor->base.dram_channels_num = 0;
 821        compressor->base.lpt_channels_num = 0;
 822        compressor->base.attached_inst = 0;
 823        compressor->base.is_enabled = false;
 824
 825        if (BP_RESULT_OK ==
 826                        bp->funcs->get_embedded_panel_info(bp, &panel_info)) {
 827                compressor->base.embedded_panel_h_size =
 828                        panel_info.lcd_timing.horizontal_addressable;
 829                compressor->base.embedded_panel_v_size =
 830                        panel_info.lcd_timing.vertical_addressable;
 831        }
 832}
 833
 834struct compressor *dce112_compressor_create(struct dc_context *ctx)
 835{
 836        struct dce112_compressor *cp110 =
 837                kzalloc(sizeof(struct dce112_compressor), GFP_KERNEL);
 838
 839        if (!cp110)
 840                return NULL;
 841
 842        dce112_compressor_construct(cp110, ctx);
 843        return &cp110->base;
 844}
 845
 846void dce112_compressor_destroy(struct compressor **compressor)
 847{
 848        kfree(TO_DCE112_COMPRESSOR(*compressor));
 849        *compressor = NULL;
 850}
 851