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