root/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c

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

DEFINITIONS

This source file includes following definitions.
  1. lpt_size_alignment
  2. lpt_memory_control_config
  3. is_source_bigger_than_epanel_size
  4. align_to_chunks_number_per_line
  5. wait_for_fbc_state_changed
  6. dce112_compressor_power_up_fbc
  7. dce112_compressor_enable_fbc
  8. dce112_compressor_disable_fbc
  9. dce112_compressor_is_fbc_enabled_in_hw
  10. dce112_compressor_is_lpt_enabled_in_hw
  11. dce112_compressor_program_compressed_surface_address_and_pitch
  12. dce112_compressor_disable_lpt
  13. dce112_compressor_enable_lpt
  14. dce112_compressor_program_lpt_control
  15. dce112_compressor_set_fbc_invalidation_triggers
  16. dce112_compressor_construct
  17. dce112_compressor_create
  18. dce112_compressor_destroy

   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 
  46 static 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 
  67 static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600;
  68 
  69 enum 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 
 101 static 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 
 108 static 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 
 271 static 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 
 286 static 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 
 293 static 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 
 319 void 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 
 365 void 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 
 417 void 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 
 442 bool 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 
 470 bool 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 
 482 void 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 
 543 void 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 
 597 void 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 
 656 void 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 
 733 void 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 
 790 void 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 
 834 struct 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 
 846 void dce112_compressor_destroy(struct compressor **compressor)
 847 {
 848         kfree(TO_DCE112_COMPRESSOR(*compressor));
 849         *compressor = NULL;
 850 }

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