linux/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.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 "dm_services.h"
  27
  28/* include DCE11 register header files */
  29#include "dce/dce_11_0_d.h"
  30#include "dce/dce_11_0_sh_mask.h"
  31
  32#include "dce110_transform_v.h"
  33
  34static void power_on_lut(struct transform *xfm,
  35        bool power_on, bool inputgamma, bool regamma)
  36{
  37        uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL);
  38        int i;
  39
  40        if (power_on) {
  41                if (inputgamma)
  42                        set_reg_field_value(
  43                                value,
  44                                1,
  45                                DCFEV_MEM_PWR_CTRL,
  46                                COL_MAN_INPUT_GAMMA_MEM_PWR_DIS);
  47                if (regamma)
  48                        set_reg_field_value(
  49                                value,
  50                                1,
  51                                DCFEV_MEM_PWR_CTRL,
  52                                COL_MAN_GAMMA_CORR_MEM_PWR_DIS);
  53        } else {
  54                if (inputgamma)
  55                        set_reg_field_value(
  56                                value,
  57                                0,
  58                                DCFEV_MEM_PWR_CTRL,
  59                                COL_MAN_INPUT_GAMMA_MEM_PWR_DIS);
  60                if (regamma)
  61                        set_reg_field_value(
  62                                value,
  63                                0,
  64                                DCFEV_MEM_PWR_CTRL,
  65                                COL_MAN_GAMMA_CORR_MEM_PWR_DIS);
  66        }
  67
  68        dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value);
  69
  70        for (i = 0; i < 3; i++) {
  71                value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL);
  72                if (get_reg_field_value(value,
  73                                DCFEV_MEM_PWR_CTRL,
  74                                COL_MAN_INPUT_GAMMA_MEM_PWR_DIS) &&
  75                        get_reg_field_value(value,
  76                                        DCFEV_MEM_PWR_CTRL,
  77                                        COL_MAN_GAMMA_CORR_MEM_PWR_DIS))
  78                        break;
  79
  80                udelay(2);
  81        }
  82}
  83
  84static void set_bypass_input_gamma(struct dce_transform *xfm_dce)
  85{
  86        uint32_t value;
  87
  88        value = dm_read_reg(xfm_dce->base.ctx,
  89                        mmCOL_MAN_INPUT_GAMMA_CONTROL1);
  90
  91        set_reg_field_value(
  92                                value,
  93                                0,
  94                                COL_MAN_INPUT_GAMMA_CONTROL1,
  95                                INPUT_GAMMA_MODE);
  96
  97        dm_write_reg(xfm_dce->base.ctx,
  98                        mmCOL_MAN_INPUT_GAMMA_CONTROL1, value);
  99}
 100
 101static void configure_regamma_mode(struct dce_transform *xfm_dce, uint32_t mode)
 102{
 103        uint32_t value = 0;
 104
 105        set_reg_field_value(
 106                                value,
 107                                mode,
 108                                GAMMA_CORR_CONTROL,
 109                                GAMMA_CORR_MODE);
 110
 111        dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CONTROL, 0);
 112}
 113
 114/*
 115 *****************************************************************************
 116 *  Function: regamma_config_regions_and_segments
 117 *
 118 *     build regamma curve by using predefined hw points
 119 *     uses interface parameters ,like EDID coeff.
 120 *
 121 * @param   : parameters   interface parameters
 122 *  @return void
 123 *
 124 *  @note
 125 *
 126 *  @see
 127 *
 128 *****************************************************************************
 129 */
 130static void regamma_config_regions_and_segments(
 131        struct dce_transform *xfm_dce, const struct pwl_params *params)
 132{
 133        const struct gamma_curve *curve;
 134        uint32_t value = 0;
 135
 136        {
 137                set_reg_field_value(
 138                        value,
 139                        params->arr_points[0].custom_float_x,
 140                        GAMMA_CORR_CNTLA_START_CNTL,
 141                        GAMMA_CORR_CNTLA_EXP_REGION_START);
 142
 143                set_reg_field_value(
 144                        value,
 145                        0,
 146                        GAMMA_CORR_CNTLA_START_CNTL,
 147                        GAMMA_CORR_CNTLA_EXP_REGION_START_SEGMENT);
 148
 149                dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_START_CNTL,
 150                                value);
 151        }
 152        {
 153                value = 0;
 154                set_reg_field_value(
 155                        value,
 156                        params->arr_points[0].custom_float_slope,
 157                        GAMMA_CORR_CNTLA_SLOPE_CNTL,
 158                        GAMMA_CORR_CNTLA_EXP_REGION_LINEAR_SLOPE);
 159
 160                dm_write_reg(xfm_dce->base.ctx,
 161                        mmGAMMA_CORR_CNTLA_SLOPE_CNTL, value);
 162        }
 163        {
 164                value = 0;
 165                set_reg_field_value(
 166                        value,
 167                        params->arr_points[1].custom_float_x,
 168                        GAMMA_CORR_CNTLA_END_CNTL1,
 169                        GAMMA_CORR_CNTLA_EXP_REGION_END);
 170
 171                dm_write_reg(xfm_dce->base.ctx,
 172                        mmGAMMA_CORR_CNTLA_END_CNTL1, value);
 173        }
 174        {
 175                value = 0;
 176                set_reg_field_value(
 177                        value,
 178                        params->arr_points[1].custom_float_slope,
 179                        GAMMA_CORR_CNTLA_END_CNTL2,
 180                        GAMMA_CORR_CNTLA_EXP_REGION_END_BASE);
 181
 182                set_reg_field_value(
 183                        value,
 184                        params->arr_points[1].custom_float_y,
 185                        GAMMA_CORR_CNTLA_END_CNTL2,
 186                        GAMMA_CORR_CNTLA_EXP_REGION_END_SLOPE);
 187
 188                dm_write_reg(xfm_dce->base.ctx,
 189                        mmGAMMA_CORR_CNTLA_END_CNTL2, value);
 190        }
 191
 192        curve = params->arr_curve_points;
 193
 194        {
 195                value = 0;
 196                set_reg_field_value(
 197                        value,
 198                        curve[0].offset,
 199                        GAMMA_CORR_CNTLA_REGION_0_1,
 200                        GAMMA_CORR_CNTLA_EXP_REGION0_LUT_OFFSET);
 201
 202                set_reg_field_value(
 203                        value,
 204                        curve[0].segments_num,
 205                        GAMMA_CORR_CNTLA_REGION_0_1,
 206                        GAMMA_CORR_CNTLA_EXP_REGION0_NUM_SEGMENTS);
 207
 208                set_reg_field_value(
 209                        value,
 210                        curve[1].offset,
 211                        GAMMA_CORR_CNTLA_REGION_0_1,
 212                        GAMMA_CORR_CNTLA_EXP_REGION1_LUT_OFFSET);
 213
 214                set_reg_field_value(
 215                        value,
 216                        curve[1].segments_num,
 217                        GAMMA_CORR_CNTLA_REGION_0_1,
 218                        GAMMA_CORR_CNTLA_EXP_REGION1_NUM_SEGMENTS);
 219
 220                dm_write_reg(
 221                                xfm_dce->base.ctx,
 222                        mmGAMMA_CORR_CNTLA_REGION_0_1,
 223                        value);
 224        }
 225
 226        curve += 2;
 227        {
 228                value = 0;
 229                set_reg_field_value(
 230                        value,
 231                        curve[0].offset,
 232                        GAMMA_CORR_CNTLA_REGION_2_3,
 233                        GAMMA_CORR_CNTLA_EXP_REGION2_LUT_OFFSET);
 234
 235                set_reg_field_value(
 236                        value,
 237                        curve[0].segments_num,
 238                        GAMMA_CORR_CNTLA_REGION_2_3,
 239                        GAMMA_CORR_CNTLA_EXP_REGION2_NUM_SEGMENTS);
 240
 241                set_reg_field_value(
 242                        value,
 243                        curve[1].offset,
 244                        GAMMA_CORR_CNTLA_REGION_2_3,
 245                        GAMMA_CORR_CNTLA_EXP_REGION3_LUT_OFFSET);
 246
 247                set_reg_field_value(
 248                        value,
 249                        curve[1].segments_num,
 250                        GAMMA_CORR_CNTLA_REGION_2_3,
 251                        GAMMA_CORR_CNTLA_EXP_REGION3_NUM_SEGMENTS);
 252
 253                dm_write_reg(xfm_dce->base.ctx,
 254                        mmGAMMA_CORR_CNTLA_REGION_2_3,
 255                        value);
 256        }
 257
 258        curve += 2;
 259        {
 260                value = 0;
 261                set_reg_field_value(
 262                        value,
 263                        curve[0].offset,
 264                        GAMMA_CORR_CNTLA_REGION_4_5,
 265                        GAMMA_CORR_CNTLA_EXP_REGION4_LUT_OFFSET);
 266
 267                set_reg_field_value(
 268                        value,
 269                        curve[0].segments_num,
 270                        GAMMA_CORR_CNTLA_REGION_4_5,
 271                        GAMMA_CORR_CNTLA_EXP_REGION4_NUM_SEGMENTS);
 272
 273                set_reg_field_value(
 274                        value,
 275                        curve[1].offset,
 276                        GAMMA_CORR_CNTLA_REGION_4_5,
 277                        GAMMA_CORR_CNTLA_EXP_REGION5_LUT_OFFSET);
 278
 279                set_reg_field_value(
 280                        value,
 281                        curve[1].segments_num,
 282                        GAMMA_CORR_CNTLA_REGION_4_5,
 283                        GAMMA_CORR_CNTLA_EXP_REGION5_NUM_SEGMENTS);
 284
 285                dm_write_reg(xfm_dce->base.ctx,
 286                        mmGAMMA_CORR_CNTLA_REGION_4_5,
 287                        value);
 288        }
 289
 290        curve += 2;
 291        {
 292                value = 0;
 293                set_reg_field_value(
 294                        value,
 295                        curve[0].offset,
 296                        GAMMA_CORR_CNTLA_REGION_6_7,
 297                        GAMMA_CORR_CNTLA_EXP_REGION6_LUT_OFFSET);
 298
 299                set_reg_field_value(
 300                        value,
 301                        curve[0].segments_num,
 302                        GAMMA_CORR_CNTLA_REGION_6_7,
 303                        GAMMA_CORR_CNTLA_EXP_REGION6_NUM_SEGMENTS);
 304
 305                set_reg_field_value(
 306                        value,
 307                        curve[1].offset,
 308                        GAMMA_CORR_CNTLA_REGION_6_7,
 309                        GAMMA_CORR_CNTLA_EXP_REGION7_LUT_OFFSET);
 310
 311                set_reg_field_value(
 312                        value,
 313                        curve[1].segments_num,
 314                        GAMMA_CORR_CNTLA_REGION_6_7,
 315                        GAMMA_CORR_CNTLA_EXP_REGION7_NUM_SEGMENTS);
 316
 317                dm_write_reg(xfm_dce->base.ctx,
 318                        mmGAMMA_CORR_CNTLA_REGION_6_7,
 319                        value);
 320        }
 321
 322        curve += 2;
 323        {
 324                value = 0;
 325                set_reg_field_value(
 326                        value,
 327                        curve[0].offset,
 328                        GAMMA_CORR_CNTLA_REGION_8_9,
 329                        GAMMA_CORR_CNTLA_EXP_REGION8_LUT_OFFSET);
 330
 331                set_reg_field_value(
 332                        value,
 333                        curve[0].segments_num,
 334                        GAMMA_CORR_CNTLA_REGION_8_9,
 335                        GAMMA_CORR_CNTLA_EXP_REGION8_NUM_SEGMENTS);
 336
 337                set_reg_field_value(
 338                        value,
 339                        curve[1].offset,
 340                        GAMMA_CORR_CNTLA_REGION_8_9,
 341                        GAMMA_CORR_CNTLA_EXP_REGION9_LUT_OFFSET);
 342
 343                set_reg_field_value(
 344                        value,
 345                        curve[1].segments_num,
 346                        GAMMA_CORR_CNTLA_REGION_8_9,
 347                        GAMMA_CORR_CNTLA_EXP_REGION9_NUM_SEGMENTS);
 348
 349                dm_write_reg(xfm_dce->base.ctx,
 350                        mmGAMMA_CORR_CNTLA_REGION_8_9,
 351                        value);
 352        }
 353
 354        curve += 2;
 355        {
 356                value = 0;
 357                set_reg_field_value(
 358                        value,
 359                        curve[0].offset,
 360                        GAMMA_CORR_CNTLA_REGION_10_11,
 361                        GAMMA_CORR_CNTLA_EXP_REGION10_LUT_OFFSET);
 362
 363                set_reg_field_value(
 364                        value,
 365                        curve[0].segments_num,
 366                        GAMMA_CORR_CNTLA_REGION_10_11,
 367                        GAMMA_CORR_CNTLA_EXP_REGION10_NUM_SEGMENTS);
 368
 369                set_reg_field_value(
 370                        value,
 371                        curve[1].offset,
 372                        GAMMA_CORR_CNTLA_REGION_10_11,
 373                        GAMMA_CORR_CNTLA_EXP_REGION11_LUT_OFFSET);
 374
 375                set_reg_field_value(
 376                        value,
 377                        curve[1].segments_num,
 378                        GAMMA_CORR_CNTLA_REGION_10_11,
 379                        GAMMA_CORR_CNTLA_EXP_REGION11_NUM_SEGMENTS);
 380
 381                dm_write_reg(xfm_dce->base.ctx,
 382                        mmGAMMA_CORR_CNTLA_REGION_10_11,
 383                        value);
 384        }
 385
 386        curve += 2;
 387        {
 388                value = 0;
 389                set_reg_field_value(
 390                        value,
 391                        curve[0].offset,
 392                        GAMMA_CORR_CNTLA_REGION_12_13,
 393                        GAMMA_CORR_CNTLA_EXP_REGION12_LUT_OFFSET);
 394
 395                set_reg_field_value(
 396                        value,
 397                        curve[0].segments_num,
 398                        GAMMA_CORR_CNTLA_REGION_12_13,
 399                        GAMMA_CORR_CNTLA_EXP_REGION12_NUM_SEGMENTS);
 400
 401                set_reg_field_value(
 402                        value,
 403                        curve[1].offset,
 404                        GAMMA_CORR_CNTLA_REGION_12_13,
 405                        GAMMA_CORR_CNTLA_EXP_REGION13_LUT_OFFSET);
 406
 407                set_reg_field_value(
 408                        value,
 409                        curve[1].segments_num,
 410                        GAMMA_CORR_CNTLA_REGION_12_13,
 411                        GAMMA_CORR_CNTLA_EXP_REGION13_NUM_SEGMENTS);
 412
 413                dm_write_reg(xfm_dce->base.ctx,
 414                        mmGAMMA_CORR_CNTLA_REGION_12_13,
 415                        value);
 416        }
 417
 418        curve += 2;
 419        {
 420                value = 0;
 421                set_reg_field_value(
 422                        value,
 423                        curve[0].offset,
 424                        GAMMA_CORR_CNTLA_REGION_14_15,
 425                        GAMMA_CORR_CNTLA_EXP_REGION14_LUT_OFFSET);
 426
 427                set_reg_field_value(
 428                        value,
 429                        curve[0].segments_num,
 430                        GAMMA_CORR_CNTLA_REGION_14_15,
 431                        GAMMA_CORR_CNTLA_EXP_REGION14_NUM_SEGMENTS);
 432
 433                set_reg_field_value(
 434                        value,
 435                        curve[1].offset,
 436                        GAMMA_CORR_CNTLA_REGION_14_15,
 437                        GAMMA_CORR_CNTLA_EXP_REGION15_LUT_OFFSET);
 438
 439                set_reg_field_value(
 440                        value,
 441                        curve[1].segments_num,
 442                        GAMMA_CORR_CNTLA_REGION_14_15,
 443                        GAMMA_CORR_CNTLA_EXP_REGION15_NUM_SEGMENTS);
 444
 445                dm_write_reg(xfm_dce->base.ctx,
 446                        mmGAMMA_CORR_CNTLA_REGION_14_15,
 447                        value);
 448        }
 449}
 450
 451static void program_pwl(struct dce_transform *xfm_dce,
 452                const struct pwl_params *params)
 453{
 454        uint32_t value = 0;
 455
 456        set_reg_field_value(
 457                value,
 458                7,
 459                GAMMA_CORR_LUT_WRITE_EN_MASK,
 460                GAMMA_CORR_LUT_WRITE_EN_MASK);
 461
 462        dm_write_reg(xfm_dce->base.ctx,
 463                mmGAMMA_CORR_LUT_WRITE_EN_MASK, value);
 464
 465        dm_write_reg(xfm_dce->base.ctx,
 466                mmGAMMA_CORR_LUT_INDEX, 0);
 467
 468        /* Program REGAMMA_LUT_DATA */
 469        {
 470                const uint32_t addr = mmGAMMA_CORR_LUT_DATA;
 471                uint32_t i = 0;
 472                const struct pwl_result_data *rgb =
 473                                params->rgb_resulted;
 474
 475                while (i != params->hw_points_num) {
 476                        dm_write_reg(xfm_dce->base.ctx, addr, rgb->red_reg);
 477                        dm_write_reg(xfm_dce->base.ctx, addr, rgb->green_reg);
 478                        dm_write_reg(xfm_dce->base.ctx, addr, rgb->blue_reg);
 479
 480                        dm_write_reg(xfm_dce->base.ctx, addr,
 481                                rgb->delta_red_reg);
 482                        dm_write_reg(xfm_dce->base.ctx, addr,
 483                                rgb->delta_green_reg);
 484                        dm_write_reg(xfm_dce->base.ctx, addr,
 485                                rgb->delta_blue_reg);
 486
 487                        ++rgb;
 488                        ++i;
 489                }
 490        }
 491}
 492
 493void dce110_opp_program_regamma_pwl_v(
 494        struct transform *xfm,
 495        const struct pwl_params *params)
 496{
 497        struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
 498
 499        /* Setup regions */
 500        regamma_config_regions_and_segments(xfm_dce, params);
 501
 502        set_bypass_input_gamma(xfm_dce);
 503
 504        /* Power on gamma LUT memory */
 505        power_on_lut(xfm, true, false, true);
 506
 507        /* Program PWL */
 508        program_pwl(xfm_dce, params);
 509
 510        /* program regamma config */
 511        configure_regamma_mode(xfm_dce, 1);
 512
 513        /* Power return to auto back */
 514        power_on_lut(xfm, false, false, true);
 515}
 516
 517void dce110_opp_power_on_regamma_lut_v(
 518        struct transform *xfm,
 519        bool power_on)
 520{
 521        uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL);
 522
 523        set_reg_field_value(
 524                value,
 525                0,
 526                DCFEV_MEM_PWR_CTRL,
 527                COL_MAN_GAMMA_CORR_MEM_PWR_FORCE);
 528
 529        set_reg_field_value(
 530                value,
 531                power_on,
 532                DCFEV_MEM_PWR_CTRL,
 533                COL_MAN_GAMMA_CORR_MEM_PWR_DIS);
 534
 535        set_reg_field_value(
 536                value,
 537                0,
 538                DCFEV_MEM_PWR_CTRL,
 539                COL_MAN_INPUT_GAMMA_MEM_PWR_FORCE);
 540
 541        set_reg_field_value(
 542                value,
 543                power_on,
 544                DCFEV_MEM_PWR_CTRL,
 545                COL_MAN_INPUT_GAMMA_MEM_PWR_DIS);
 546
 547        dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value);
 548}
 549
 550void dce110_opp_set_regamma_mode_v(
 551        struct transform *xfm,
 552        enum opp_regamma mode)
 553{
 554        // TODO: need to implement the function
 555}
 556