linux/drivers/gpu/drm/amd/display/dc/dce/dce_opp.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/slab.h>
  27
  28#include "dm_services.h"
  29#include "basics/conversion.h"
  30
  31#include "dce_opp.h"
  32
  33#include "reg_helper.h"
  34
  35#define REG(reg)\
  36        (opp110->regs->reg)
  37
  38#undef FN
  39#define FN(reg_name, field_name) \
  40        opp110->opp_shift->field_name, opp110->opp_mask->field_name
  41
  42#define CTX \
  43        opp110->base.ctx
  44
  45enum {
  46        MAX_PWL_ENTRY = 128,
  47        MAX_REGIONS_NUMBER = 16
  48};
  49
  50enum {
  51        MAX_LUT_ENTRY = 256,
  52        MAX_NUMBER_OF_ENTRIES = 256
  53};
  54
  55
  56enum {
  57        OUTPUT_CSC_MATRIX_SIZE = 12
  58};
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81/*
  82 *****************************************************************************
  83 *  Function: regamma_config_regions_and_segments
  84 *
  85 *     build regamma curve by using predefined hw points
  86 *     uses interface parameters ,like EDID coeff.
  87 *
  88 * @param   : parameters   interface parameters
  89 *  @return void
  90 *
  91 *  @note
  92 *
  93 *  @see
  94 *
  95 *****************************************************************************
  96 */
  97
  98
  99
 100/*
 101 *      set_truncation
 102 *      1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
 103 *      2) enable truncation
 104 *      3) HW remove 12bit FMT support for DCE11 power saving reason.
 105 */
 106static void set_truncation(
 107                struct dce110_opp *opp110,
 108                const struct bit_depth_reduction_params *params)
 109{
 110        /*Disable truncation*/
 111        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 112                        FMT_TRUNCATE_EN, 0,
 113                        FMT_TRUNCATE_DEPTH, 0,
 114                        FMT_TRUNCATE_MODE, 0);
 115
 116
 117        if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
 118                /*  8bpc trunc on YCbCr422*/
 119                if (params->flags.TRUNCATE_DEPTH == 1)
 120                        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 121                                        FMT_TRUNCATE_EN, 1,
 122                                        FMT_TRUNCATE_DEPTH, 1,
 123                                        FMT_TRUNCATE_MODE, 0);
 124                else if (params->flags.TRUNCATE_DEPTH == 2)
 125                        /*  10bpc trunc on YCbCr422*/
 126                        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 127                                        FMT_TRUNCATE_EN, 1,
 128                                        FMT_TRUNCATE_DEPTH, 2,
 129                                        FMT_TRUNCATE_MODE, 0);
 130                return;
 131        }
 132        /* on other format-to do */
 133        if (params->flags.TRUNCATE_ENABLED == 0)
 134                return;
 135        /*Set truncation depth and Enable truncation*/
 136        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 137                                FMT_TRUNCATE_EN, 1,
 138                                FMT_TRUNCATE_DEPTH,
 139                                params->flags.TRUNCATE_DEPTH,
 140                                FMT_TRUNCATE_MODE,
 141                                params->flags.TRUNCATE_MODE);
 142}
 143
 144#if defined(CONFIG_DRM_AMD_DC_SI)
 145/*
 146 *      dce60_set_truncation
 147 *      1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
 148 *      2) enable truncation
 149 *      3) HW remove 12bit FMT support for DCE11 power saving reason.
 150 */
 151static void dce60_set_truncation(
 152                struct dce110_opp *opp110,
 153                const struct bit_depth_reduction_params *params)
 154{
 155        /* DCE6 has no FMT_TRUNCATE_MODE bit in FMT_BIT_DEPTH_CONTROL reg */
 156
 157        /*Disable truncation*/
 158        REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
 159                        FMT_TRUNCATE_EN, 0,
 160                        FMT_TRUNCATE_DEPTH, 0);
 161
 162        if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
 163                /*  8bpc trunc on YCbCr422*/
 164                if (params->flags.TRUNCATE_DEPTH == 1)
 165                        REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
 166                                        FMT_TRUNCATE_EN, 1,
 167                                        FMT_TRUNCATE_DEPTH, 1);
 168                else if (params->flags.TRUNCATE_DEPTH == 2)
 169                        /*  10bpc trunc on YCbCr422*/
 170                        REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
 171                                        FMT_TRUNCATE_EN, 1,
 172                                        FMT_TRUNCATE_DEPTH, 2);
 173                return;
 174        }
 175        /* on other format-to do */
 176        if (params->flags.TRUNCATE_ENABLED == 0)
 177                return;
 178        /*Set truncation depth and Enable truncation*/
 179        REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
 180                                FMT_TRUNCATE_EN, 1,
 181                                FMT_TRUNCATE_DEPTH,
 182                                params->flags.TRUNCATE_DEPTH);
 183}
 184#endif
 185
 186/*
 187 *      set_spatial_dither
 188 *      1) set spatial dithering mode: pattern of seed
 189 *      2) set spatial dithering depth: 0 for 18bpp or 1 for 24bpp
 190 *      3) set random seed
 191 *      4) set random mode
 192 *              lfsr is reset every frame or not reset
 193 *              RGB dithering method
 194 *              0: RGB data are all dithered with x^28+x^3+1
 195 *              1: R data is dithered with x^28+x^3+1
 196 *              G data is dithered with x^28+X^9+1
 197 *              B data is dithered with x^28+x^13+1
 198 *              enable high pass filter or not
 199 *      5) enable spatical dithering
 200 */
 201static void set_spatial_dither(
 202        struct dce110_opp *opp110,
 203        const struct bit_depth_reduction_params *params)
 204{
 205        /*Disable spatial (random) dithering*/
 206        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 207                FMT_SPATIAL_DITHER_EN, 0,
 208                FMT_SPATIAL_DITHER_DEPTH, 0,
 209                FMT_SPATIAL_DITHER_MODE, 0);
 210
 211        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 212                FMT_HIGHPASS_RANDOM_ENABLE, 0,
 213                FMT_FRAME_RANDOM_ENABLE, 0,
 214                FMT_RGB_RANDOM_ENABLE, 0);
 215
 216        REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
 217                FMT_TEMPORAL_DITHER_EN, 0);
 218
 219        if (params->flags.SPATIAL_DITHER_ENABLED == 0)
 220                return;
 221
 222        /* only use FRAME_COUNTER_MAX if frameRandom == 1*/
 223
 224        if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX &&
 225                        opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) {
 226                if (params->flags.FRAME_RANDOM == 1) {
 227                        if (params->flags.SPATIAL_DITHER_DEPTH == 0 ||
 228                        params->flags.SPATIAL_DITHER_DEPTH == 1) {
 229                                REG_UPDATE_2(FMT_CONTROL,
 230                                        FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
 231                                        FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
 232                        } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
 233                                REG_UPDATE_2(FMT_CONTROL,
 234                                        FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
 235                                        FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
 236                        } else
 237                                return;
 238                } else {
 239                        REG_UPDATE_2(FMT_CONTROL,
 240                                        FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
 241                                        FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
 242                }
 243        }
 244        /* Set seed for random values for
 245         * spatial dithering for R,G,B channels
 246         */
 247        REG_UPDATE(FMT_DITHER_RAND_R_SEED,
 248                        FMT_RAND_R_SEED, params->r_seed_value);
 249
 250        REG_UPDATE(FMT_DITHER_RAND_G_SEED,
 251                        FMT_RAND_G_SEED, params->g_seed_value);
 252
 253        REG_UPDATE(FMT_DITHER_RAND_B_SEED,
 254                        FMT_RAND_B_SEED, params->b_seed_value);
 255
 256        /* FMT_OFFSET_R_Cr  31:16 0x0 Setting the zero
 257         * offset for the R/Cr channel, lower 4LSB
 258         * is forced to zeros. Typically set to 0
 259         * RGB and 0x80000 YCbCr.
 260         */
 261        /* FMT_OFFSET_G_Y   31:16 0x0 Setting the zero
 262         * offset for the G/Y  channel, lower 4LSB is
 263         * forced to zeros. Typically set to 0 RGB
 264         * and 0x80000 YCbCr.
 265         */
 266        /* FMT_OFFSET_B_Cb  31:16 0x0 Setting the zero
 267         * offset for the B/Cb channel, lower 4LSB is
 268         * forced to zeros. Typically set to 0 RGB and
 269         * 0x80000 YCbCr.
 270         */
 271
 272        /* Disable High pass filter
 273         * Reset only at startup
 274         * Set RGB data dithered with x^28+x^3+1
 275         */
 276        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 277                FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
 278                FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
 279                FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
 280
 281        /* Set spatial dithering bit depth
 282         * Set spatial dithering mode
 283         * (default is Seed patterrn AAAA...)
 284         * Enable spatial dithering
 285         */
 286        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 287                FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
 288                FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
 289                FMT_SPATIAL_DITHER_EN, 1);
 290}
 291
 292/*
 293 *      SetTemporalDither (Frame Modulation)
 294 *      1) set temporal dither depth
 295 *      2) select pattern: from hard-coded pattern or programmable pattern
 296 *      3) select optimized strips for BGR or RGB LCD sub-pixel
 297 *      4) set s matrix
 298 *      5) set t matrix
 299 *      6) set grey level for 0.25, 0.5, 0.75
 300 *      7) enable temporal dithering
 301 */
 302
 303static void set_temporal_dither(
 304        struct dce110_opp *opp110,
 305        const struct bit_depth_reduction_params *params)
 306{
 307        /*Disable temporal (frame modulation) dithering first*/
 308        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 309                FMT_TEMPORAL_DITHER_EN, 0,
 310                FMT_TEMPORAL_DITHER_RESET, 0,
 311                FMT_TEMPORAL_DITHER_OFFSET, 0);
 312
 313        REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
 314                FMT_TEMPORAL_DITHER_DEPTH, 0,
 315                FMT_TEMPORAL_LEVEL, 0);
 316
 317        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 318                FMT_25FRC_SEL, 0,
 319                FMT_50FRC_SEL, 0,
 320                FMT_75FRC_SEL, 0);
 321
 322        /* no 10bpc dither on DCE11*/
 323        if (params->flags.FRAME_MODULATION_ENABLED == 0 ||
 324                params->flags.FRAME_MODULATION_DEPTH == 2)
 325                return;
 326
 327        /* Set temporal dithering depth*/
 328        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 329                FMT_TEMPORAL_DITHER_DEPTH, params->flags.FRAME_MODULATION_DEPTH,
 330                FMT_TEMPORAL_DITHER_RESET, 0,
 331                FMT_TEMPORAL_DITHER_OFFSET, 0);
 332
 333        /*Select legacy pattern based on FRC and Temporal level*/
 334        if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) {
 335                REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0);
 336                /*Set s matrix*/
 337                REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0);
 338                /*Set t matrix*/
 339                REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, 0);
 340        }
 341
 342        /*Select patterns for 0.25, 0.5 and 0.75 grey level*/
 343        REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
 344                FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL);
 345
 346        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 347                FMT_25FRC_SEL, params->flags.FRC25,
 348                FMT_50FRC_SEL, params->flags.FRC50,
 349                FMT_75FRC_SEL, params->flags.FRC75);
 350
 351        /*Enable bit reduction by temporal (frame modulation) dithering*/
 352        REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
 353                FMT_TEMPORAL_DITHER_EN, 1);
 354}
 355
 356/*
 357 *      Set Clamping
 358 *      1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
 359 *              1 for 8 bpc
 360 *              2 for 10 bpc
 361 *              3 for 12 bpc
 362 *              7 for programable
 363 *      2) Enable clamp if Limited range requested
 364 */
 365void dce110_opp_set_clamping(
 366        struct dce110_opp *opp110,
 367        const struct clamping_and_pixel_encoding_params *params)
 368{
 369        REG_SET_2(FMT_CLAMP_CNTL, 0,
 370                FMT_CLAMP_DATA_EN, 0,
 371                FMT_CLAMP_COLOR_FORMAT, 0);
 372
 373        switch (params->clamping_level) {
 374        case CLAMPING_FULL_RANGE:
 375                break;
 376        case CLAMPING_LIMITED_RANGE_8BPC:
 377                REG_SET_2(FMT_CLAMP_CNTL, 0,
 378                        FMT_CLAMP_DATA_EN, 1,
 379                        FMT_CLAMP_COLOR_FORMAT, 1);
 380                break;
 381        case CLAMPING_LIMITED_RANGE_10BPC:
 382                REG_SET_2(FMT_CLAMP_CNTL, 0,
 383                        FMT_CLAMP_DATA_EN, 1,
 384                        FMT_CLAMP_COLOR_FORMAT, 2);
 385                break;
 386        case CLAMPING_LIMITED_RANGE_12BPC:
 387                REG_SET_2(FMT_CLAMP_CNTL, 0,
 388                        FMT_CLAMP_DATA_EN, 1,
 389                        FMT_CLAMP_COLOR_FORMAT, 3);
 390                break;
 391        case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
 392                /*Set clamp control*/
 393                REG_SET_2(FMT_CLAMP_CNTL, 0,
 394                        FMT_CLAMP_DATA_EN, 1,
 395                        FMT_CLAMP_COLOR_FORMAT, 7);
 396
 397                /*set the defaults*/
 398                REG_SET_2(FMT_CLAMP_COMPONENT_R, 0,
 399                        FMT_CLAMP_LOWER_R, 0x10,
 400                        FMT_CLAMP_UPPER_R, 0xFEF);
 401
 402                REG_SET_2(FMT_CLAMP_COMPONENT_G, 0,
 403                        FMT_CLAMP_LOWER_G, 0x10,
 404                        FMT_CLAMP_UPPER_G, 0xFEF);
 405
 406                REG_SET_2(FMT_CLAMP_COMPONENT_B, 0,
 407                        FMT_CLAMP_LOWER_B, 0x10,
 408                        FMT_CLAMP_UPPER_B, 0xFEF);
 409                break;
 410        default:
 411                break;
 412        }
 413}
 414
 415#if defined(CONFIG_DRM_AMD_DC_SI)
 416/*
 417 *      Set Clamping for DCE6 parts
 418 *      1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
 419 *              1 for 8 bpc
 420 *              2 for 10 bpc
 421 *              3 for 12 bpc
 422 *              7 for programable
 423 *      2) Enable clamp if Limited range requested
 424 */
 425static void dce60_opp_set_clamping(
 426        struct dce110_opp *opp110,
 427        const struct clamping_and_pixel_encoding_params *params)
 428{
 429        REG_SET_2(FMT_CLAMP_CNTL, 0,
 430                FMT_CLAMP_DATA_EN, 0,
 431                FMT_CLAMP_COLOR_FORMAT, 0);
 432
 433        switch (params->clamping_level) {
 434        case CLAMPING_FULL_RANGE:
 435                break;
 436        case CLAMPING_LIMITED_RANGE_8BPC:
 437                REG_SET_2(FMT_CLAMP_CNTL, 0,
 438                        FMT_CLAMP_DATA_EN, 1,
 439                        FMT_CLAMP_COLOR_FORMAT, 1);
 440                break;
 441        case CLAMPING_LIMITED_RANGE_10BPC:
 442                REG_SET_2(FMT_CLAMP_CNTL, 0,
 443                        FMT_CLAMP_DATA_EN, 1,
 444                        FMT_CLAMP_COLOR_FORMAT, 2);
 445                break;
 446        case CLAMPING_LIMITED_RANGE_12BPC:
 447                REG_SET_2(FMT_CLAMP_CNTL, 0,
 448                        FMT_CLAMP_DATA_EN, 1,
 449                        FMT_CLAMP_COLOR_FORMAT, 3);
 450                break;
 451        case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
 452                /*Set clamp control*/
 453                REG_SET_2(FMT_CLAMP_CNTL, 0,
 454                        FMT_CLAMP_DATA_EN, 1,
 455                        FMT_CLAMP_COLOR_FORMAT, 7);
 456
 457                /* DCE6 does have FMT_CLAMP_COMPONENT_{R,G,B} registers */
 458
 459                break;
 460        default:
 461                break;
 462        }
 463}
 464#endif
 465
 466/*
 467 *      set_pixel_encoding
 468 *
 469 *      Set Pixel Encoding
 470 *              0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
 471 *              1: YCbCr 4:2:2
 472 */
 473static void set_pixel_encoding(
 474        struct dce110_opp *opp110,
 475        const struct clamping_and_pixel_encoding_params *params)
 476{
 477        if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS)
 478                REG_UPDATE_3(FMT_CONTROL,
 479                                FMT_PIXEL_ENCODING, 0,
 480                                FMT_SUBSAMPLING_MODE, 0,
 481                                FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
 482        else
 483                REG_UPDATE_2(FMT_CONTROL,
 484                                FMT_PIXEL_ENCODING, 0,
 485                                FMT_SUBSAMPLING_MODE, 0);
 486
 487        if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
 488                REG_UPDATE_2(FMT_CONTROL,
 489                                FMT_PIXEL_ENCODING, 1,
 490                                FMT_SUBSAMPLING_ORDER, 0);
 491        }
 492        if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
 493                REG_UPDATE_3(FMT_CONTROL,
 494                                FMT_PIXEL_ENCODING, 2,
 495                                FMT_SUBSAMPLING_MODE, 2,
 496                                FMT_CBCR_BIT_REDUCTION_BYPASS, 1);
 497        }
 498
 499}
 500
 501#if defined(CONFIG_DRM_AMD_DC_SI)
 502/*
 503 *      dce60_set_pixel_encoding
 504 *      DCE6 has no FMT_SUBSAMPLING_{MODE,ORDER} bits in FMT_CONTROL reg
 505 *      Set Pixel Encoding
 506 *              0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
 507 *              1: YCbCr 4:2:2
 508 */
 509static void dce60_set_pixel_encoding(
 510        struct dce110_opp *opp110,
 511        const struct clamping_and_pixel_encoding_params *params)
 512{
 513        if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS)
 514                REG_UPDATE_2(FMT_CONTROL,
 515                                FMT_PIXEL_ENCODING, 0,
 516                                FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
 517        else
 518                REG_UPDATE(FMT_CONTROL,
 519                                FMT_PIXEL_ENCODING, 0);
 520
 521        if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
 522                REG_UPDATE(FMT_CONTROL,
 523                                FMT_PIXEL_ENCODING, 1);
 524        }
 525        if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
 526                REG_UPDATE_2(FMT_CONTROL,
 527                                FMT_PIXEL_ENCODING, 2,
 528                                FMT_CBCR_BIT_REDUCTION_BYPASS, 1);
 529        }
 530
 531}
 532#endif
 533
 534void dce110_opp_program_bit_depth_reduction(
 535        struct output_pixel_processor *opp,
 536        const struct bit_depth_reduction_params *params)
 537{
 538        struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
 539
 540        set_truncation(opp110, params);
 541        set_spatial_dither(opp110, params);
 542        set_temporal_dither(opp110, params);
 543}
 544
 545#if defined(CONFIG_DRM_AMD_DC_SI)
 546static void dce60_opp_program_bit_depth_reduction(
 547        struct output_pixel_processor *opp,
 548        const struct bit_depth_reduction_params *params)
 549{
 550        struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
 551
 552        dce60_set_truncation(opp110, params);
 553        set_spatial_dither(opp110, params);
 554        set_temporal_dither(opp110, params);
 555}
 556#endif
 557
 558void dce110_opp_program_clamping_and_pixel_encoding(
 559        struct output_pixel_processor *opp,
 560        const struct clamping_and_pixel_encoding_params *params)
 561{
 562        struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
 563
 564        dce110_opp_set_clamping(opp110, params);
 565        set_pixel_encoding(opp110, params);
 566}
 567
 568#if defined(CONFIG_DRM_AMD_DC_SI)
 569static void dce60_opp_program_clamping_and_pixel_encoding(
 570        struct output_pixel_processor *opp,
 571        const struct clamping_and_pixel_encoding_params *params)
 572{
 573        struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
 574
 575        dce60_opp_set_clamping(opp110, params);
 576        dce60_set_pixel_encoding(opp110, params);
 577}
 578#endif
 579
 580
 581static void program_formatter_420_memory(struct output_pixel_processor *opp)
 582{
 583        struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
 584        uint32_t fmt_mem_cntl_value;
 585
 586        /* Program source select*/
 587        /* Use HW default source select for FMT_MEMORYx_CONTROL */
 588        /* Use that value for FMT_SRC_SELECT as well*/
 589        REG_GET(CONTROL,
 590                        FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value);
 591
 592        REG_UPDATE(FMT_CONTROL,
 593                        FMT_SRC_SELECT, fmt_mem_cntl_value);
 594
 595        /* Turn on the memory */
 596        REG_UPDATE(CONTROL,
 597                        FMT420_MEM0_PWR_FORCE, 0);
 598}
 599
 600void dce110_opp_set_dyn_expansion(
 601        struct output_pixel_processor *opp,
 602        enum dc_color_space color_sp,
 603        enum dc_color_depth color_dpth,
 604        enum signal_type signal)
 605{
 606        struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
 607
 608        REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
 609                        FMT_DYNAMIC_EXP_EN, 0,
 610                        FMT_DYNAMIC_EXP_MODE, 0);
 611
 612        /*00 - 10-bit -> 12-bit dynamic expansion*/
 613        /*01 - 8-bit  -> 12-bit dynamic expansion*/
 614        if (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
 615                signal == SIGNAL_TYPE_DISPLAY_PORT ||
 616                signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
 617                switch (color_dpth) {
 618                case COLOR_DEPTH_888:
 619                        REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
 620                                FMT_DYNAMIC_EXP_EN, 1,
 621                                FMT_DYNAMIC_EXP_MODE, 1);
 622                        break;
 623                case COLOR_DEPTH_101010:
 624                        REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
 625                                FMT_DYNAMIC_EXP_EN, 1,
 626                                FMT_DYNAMIC_EXP_MODE, 0);
 627                        break;
 628                case COLOR_DEPTH_121212:
 629                        REG_UPDATE_2(
 630                                FMT_DYNAMIC_EXP_CNTL,
 631                                FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/
 632                                FMT_DYNAMIC_EXP_MODE, 0);
 633                        break;
 634                default:
 635                        break;
 636                }
 637        }
 638}
 639
 640static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp)
 641{
 642        struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
 643
 644        /* clear previous phase lock status*/
 645        REG_UPDATE(FMT_CONTROL,
 646                        FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1);
 647
 648        /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/
 649        REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10);
 650
 651}
 652
 653void dce110_opp_program_fmt(
 654        struct output_pixel_processor *opp,
 655        struct bit_depth_reduction_params *fmt_bit_depth,
 656        struct clamping_and_pixel_encoding_params *clamping)
 657{
 658        /* dithering is affected by <CrtcSourceSelect>, hence should be
 659         * programmed afterwards */
 660
 661        if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
 662                program_formatter_420_memory(opp);
 663
 664        dce110_opp_program_bit_depth_reduction(
 665                opp,
 666                fmt_bit_depth);
 667
 668        dce110_opp_program_clamping_and_pixel_encoding(
 669                opp,
 670                clamping);
 671
 672        if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
 673                program_formatter_reset_dig_resync_fifo(opp);
 674
 675        return;
 676}
 677
 678#if defined(CONFIG_DRM_AMD_DC_SI)
 679static void dce60_opp_program_fmt(
 680        struct output_pixel_processor *opp,
 681        struct bit_depth_reduction_params *fmt_bit_depth,
 682        struct clamping_and_pixel_encoding_params *clamping)
 683{
 684        /* dithering is affected by <CrtcSourceSelect>, hence should be
 685         * programmed afterwards */
 686
 687        if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
 688                program_formatter_420_memory(opp);
 689
 690        dce60_opp_program_bit_depth_reduction(
 691                opp,
 692                fmt_bit_depth);
 693
 694        dce60_opp_program_clamping_and_pixel_encoding(
 695                opp,
 696                clamping);
 697
 698        if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
 699                program_formatter_reset_dig_resync_fifo(opp);
 700
 701        return;
 702}
 703#endif
 704
 705
 706
 707/*****************************************/
 708/* Constructor, Destructor               */
 709/*****************************************/
 710
 711static const struct opp_funcs funcs = {
 712        .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
 713        .opp_destroy = dce110_opp_destroy,
 714        .opp_program_fmt = dce110_opp_program_fmt,
 715        .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction
 716};
 717
 718#if defined(CONFIG_DRM_AMD_DC_SI)
 719static const struct opp_funcs dce60_opp_funcs = {
 720        .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
 721        .opp_destroy = dce110_opp_destroy,
 722        .opp_program_fmt = dce60_opp_program_fmt,
 723        .opp_program_bit_depth_reduction = dce60_opp_program_bit_depth_reduction
 724};
 725#endif
 726
 727void dce110_opp_construct(struct dce110_opp *opp110,
 728        struct dc_context *ctx,
 729        uint32_t inst,
 730        const struct dce_opp_registers *regs,
 731        const struct dce_opp_shift *opp_shift,
 732        const struct dce_opp_mask *opp_mask)
 733{
 734        opp110->base.funcs = &funcs;
 735
 736        opp110->base.ctx = ctx;
 737
 738        opp110->base.inst = inst;
 739
 740        opp110->regs = regs;
 741        opp110->opp_shift = opp_shift;
 742        opp110->opp_mask = opp_mask;
 743}
 744
 745#if defined(CONFIG_DRM_AMD_DC_SI)
 746void dce60_opp_construct(struct dce110_opp *opp110,
 747        struct dc_context *ctx,
 748        uint32_t inst,
 749        const struct dce_opp_registers *regs,
 750        const struct dce_opp_shift *opp_shift,
 751        const struct dce_opp_mask *opp_mask)
 752{
 753        opp110->base.funcs = &dce60_opp_funcs;
 754
 755        opp110->base.ctx = ctx;
 756
 757        opp110->base.inst = inst;
 758
 759        opp110->regs = regs;
 760        opp110->opp_shift = opp_shift;
 761        opp110->opp_mask = opp_mask;
 762}
 763#endif
 764
 765void dce110_opp_destroy(struct output_pixel_processor **opp)
 766{
 767        if (*opp)
 768                kfree(FROM_DCE11_OPP(*opp));
 769        *opp = NULL;
 770}
 771
 772