linux/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.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 "dce/dce_12_0_offset.h"
  29#include "dce/dce_12_0_sh_mask.h"
  30#include "soc15_hw_ip.h"
  31#include "vega10_ip_offset.h"
  32
  33#include "dc_types.h"
  34#include "dc_bios_types.h"
  35
  36#include "include/grph_object_id.h"
  37#include "include/logger_interface.h"
  38#include "dce120_timing_generator.h"
  39
  40#include "timing_generator.h"
  41
  42#define CRTC_REG_UPDATE_N(reg_name, n, ...)     \
  43                generic_reg_update_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__)
  44
  45#define CRTC_REG_SET_N(reg_name, n, ...)        \
  46                generic_reg_set_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__)
  47
  48#define CRTC_REG_UPDATE(reg, field, val)        \
  49                CRTC_REG_UPDATE_N(reg, 1, FD(reg##__##field), val)
  50
  51#define CRTC_REG_UPDATE_2(reg, field1, val1, field2, val2)      \
  52                CRTC_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2)
  53
  54#define CRTC_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3)        \
  55                CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3)
  56
  57#define CRTC_REG_UPDATE_4(reg, field1, val1, field2, val2, field3, val3, field4, val4)  \
  58                CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4)
  59
  60#define CRTC_REG_UPDATE_5(reg, field1, val1, field2, val2, field3, val3, field4, val4, field5, val5)    \
  61                CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4, FD(reg##__##field5), val5)
  62
  63#define CRTC_REG_SET(reg, field, val)   \
  64                CRTC_REG_SET_N(reg, 1, FD(reg##__##field), val)
  65
  66#define CRTC_REG_SET_2(reg, field1, val1, field2, val2) \
  67                CRTC_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2)
  68
  69#define CRTC_REG_SET_3(reg, field1, val1, field2, val2, field3, val3)   \
  70                CRTC_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3)
  71
  72/**
  73 *****************************************************************************
  74 *  Function: is_in_vertical_blank
  75 *
  76 *  @brief
  77 *     check the current status of CRTC to check if we are in Vertical Blank
  78 *     regioneased" state
  79 *
  80 *  @return
  81 *     true if currently in blank region, false otherwise
  82 *
  83 *****************************************************************************
  84 */
  85static bool dce120_timing_generator_is_in_vertical_blank(
  86                struct timing_generator *tg)
  87{
  88        uint32_t field = 0;
  89        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
  90        uint32_t value = dm_read_reg_soc15(
  91                                        tg->ctx,
  92                                        mmCRTC0_CRTC_STATUS,
  93                                        tg110->offsets.crtc);
  94
  95        field = get_reg_field_value(value, CRTC0_CRTC_STATUS, CRTC_V_BLANK);
  96        return field == 1;
  97}
  98
  99
 100/* determine if given timing can be supported by TG */
 101bool dce120_timing_generator_validate_timing(
 102        struct timing_generator *tg,
 103        const struct dc_crtc_timing *timing,
 104        enum signal_type signal)
 105{
 106        uint32_t interlace_factor = timing->flags.INTERLACE ? 2 : 1;
 107        uint32_t v_blank =
 108                                        (timing->v_total - timing->v_addressable -
 109                                        timing->v_border_top - timing->v_border_bottom) *
 110                                        interlace_factor;
 111        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 112
 113        if (!dce110_timing_generator_validate_timing(
 114                                        tg,
 115                                        timing,
 116                                        signal))
 117                return false;
 118
 119
 120        if (v_blank < tg110->min_v_blank        ||
 121                 timing->h_sync_width  < tg110->min_h_sync_width ||
 122                 timing->v_sync_width  < tg110->min_v_sync_width)
 123                return false;
 124
 125        return true;
 126}
 127
 128bool dce120_tg_validate_timing(struct timing_generator *tg,
 129        const struct dc_crtc_timing *timing)
 130{
 131        return dce120_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE);
 132}
 133
 134/******** HW programming ************/
 135/* Disable/Enable Timing Generator */
 136bool dce120_timing_generator_enable_crtc(struct timing_generator *tg)
 137{
 138        enum bp_result result;
 139        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 140
 141        /* Set MASTER_UPDATE_MODE to 0
 142         * This is needed for DRR, and also suggested to be default value by Syed.*/
 143
 144        CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_MODE,
 145                        MASTER_UPDATE_MODE, 0);
 146
 147        CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_LOCK,
 148                        UNDERFLOW_UPDATE_LOCK, 0);
 149
 150        /* TODO API for AtomFirmware didn't change*/
 151        result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true);
 152
 153        return result == BP_RESULT_OK;
 154}
 155
 156void dce120_timing_generator_set_early_control(
 157                struct timing_generator *tg,
 158                uint32_t early_cntl)
 159{
 160        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 161
 162        CRTC_REG_UPDATE(CRTC0_CRTC_CONTROL,
 163                        CRTC_HBLANK_EARLY_CONTROL, early_cntl);
 164}
 165
 166/**************** TG current status ******************/
 167
 168/* return the current frame counter. Used by Linux kernel DRM */
 169uint32_t dce120_timing_generator_get_vblank_counter(
 170                struct timing_generator *tg)
 171{
 172        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 173        uint32_t value = dm_read_reg_soc15(
 174                                tg->ctx,
 175                                mmCRTC0_CRTC_STATUS_FRAME_COUNT,
 176                                tg110->offsets.crtc);
 177        uint32_t field = get_reg_field_value(
 178                                value, CRTC0_CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
 179
 180        return field;
 181}
 182
 183/* Get current H and V position */
 184void dce120_timing_generator_get_crtc_position(
 185        struct timing_generator *tg,
 186        struct crtc_position *position)
 187{
 188        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 189        uint32_t value = dm_read_reg_soc15(
 190                                tg->ctx,
 191                                mmCRTC0_CRTC_STATUS_POSITION,
 192                                tg110->offsets.crtc);
 193
 194        position->horizontal_count = get_reg_field_value(value,
 195                        CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT);
 196
 197        position->vertical_count = get_reg_field_value(value,
 198                        CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT);
 199
 200        value = dm_read_reg_soc15(
 201                                tg->ctx,
 202                                mmCRTC0_CRTC_NOM_VERT_POSITION,
 203                                tg110->offsets.crtc);
 204
 205        position->nominal_vcount = get_reg_field_value(value,
 206                        CRTC0_CRTC_NOM_VERT_POSITION, CRTC_VERT_COUNT_NOM);
 207}
 208
 209/* wait until TG is in beginning of vertical blank region */
 210void dce120_timing_generator_wait_for_vblank(struct timing_generator *tg)
 211{
 212        /* We want to catch beginning of VBlank here, so if the first try are
 213         * in VBlank, we might be very close to Active, in this case wait for
 214         * another frame
 215         */
 216        while (dce120_timing_generator_is_in_vertical_blank(tg)) {
 217                if (!tg->funcs->is_counter_moving(tg)) {
 218                        /* error - no point to wait if counter is not moving */
 219                        break;
 220                }
 221        }
 222
 223        while (!dce120_timing_generator_is_in_vertical_blank(tg)) {
 224                if (!tg->funcs->is_counter_moving(tg)) {
 225                        /* error - no point to wait if counter is not moving */
 226                        break;
 227                }
 228        }
 229}
 230
 231/* wait until TG is in beginning of active region */
 232void dce120_timing_generator_wait_for_vactive(struct timing_generator *tg)
 233{
 234        while (dce120_timing_generator_is_in_vertical_blank(tg)) {
 235                if (!tg->funcs->is_counter_moving(tg)) {
 236                        /* error - no point to wait if counter is not moving */
 237                        break;
 238                }
 239        }
 240}
 241
 242/*********** Timing Generator Synchronization routines ****/
 243
 244/* Setups Global Swap Lock group, TimingServer or TimingClient*/
 245void dce120_timing_generator_setup_global_swap_lock(
 246        struct timing_generator *tg,
 247        const struct dcp_gsl_params *gsl_params)
 248{
 249        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 250        uint32_t value_crtc_vtotal =
 251                                                        dm_read_reg_soc15(tg->ctx,
 252                                                        mmCRTC0_CRTC_V_TOTAL,
 253                                                        tg110->offsets.crtc);
 254        /* Checkpoint relative to end of frame */
 255        uint32_t check_point =
 256                                                        get_reg_field_value(value_crtc_vtotal,
 257                                                        CRTC0_CRTC_V_TOTAL,
 258                                                        CRTC_V_TOTAL);
 259
 260
 261        dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_GSL_WINDOW, tg110->offsets.crtc, 0);
 262
 263        CRTC_REG_UPDATE_N(DCP0_DCP_GSL_CONTROL, 6,
 264                /* This pipe will belong to GSL Group zero. */
 265                FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 1,
 266                FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), gsl_params->gsl_master == tg->inst,
 267                FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY,
 268                /* Keep signal low (pending high) during 6 lines.
 269                 * Also defines minimum interval before re-checking signal. */
 270                FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY,
 271                /* DCP_GSL_PURPOSE_SURFACE_FLIP */
 272                FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0,
 273                FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 1);
 274
 275        CRTC_REG_SET_2(
 276                        CRTC0_CRTC_GSL_CONTROL,
 277                        CRTC_GSL_CHECK_LINE_NUM, check_point - FLIP_READY_BACK_LOOKUP,
 278                        CRTC_GSL_FORCE_DELAY, VFLIP_READY_DELAY);
 279}
 280
 281/* Clear all the register writes done by setup_global_swap_lock */
 282void dce120_timing_generator_tear_down_global_swap_lock(
 283        struct timing_generator *tg)
 284{
 285        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 286
 287        /* Settig HW default values from reg specs */
 288        CRTC_REG_SET_N(DCP0_DCP_GSL_CONTROL, 6,
 289                        FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 0,
 290                        FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), 0,
 291                        FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY,
 292                        FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY,
 293                        /* DCP_GSL_PURPOSE_SURFACE_FLIP */
 294                        FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0,
 295                        FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 0);
 296
 297        CRTC_REG_SET_2(CRTC0_CRTC_GSL_CONTROL,
 298                       CRTC_GSL_CHECK_LINE_NUM, 0,
 299                       CRTC_GSL_FORCE_DELAY, 0x2); /*TODO Why this value here ?*/
 300}
 301
 302/* Reset slave controllers on master VSync */
 303void dce120_timing_generator_enable_reset_trigger(
 304        struct timing_generator *tg,
 305        int source)
 306{
 307        enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
 308        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 309        uint32_t rising_edge = 0;
 310        uint32_t falling_edge = 0;
 311        /* Setup trigger edge */
 312        uint32_t pol_value = dm_read_reg_soc15(
 313                                                                        tg->ctx,
 314                                                                        mmCRTC0_CRTC_V_SYNC_A_CNTL,
 315                                                                        tg110->offsets.crtc);
 316
 317        /* Register spec has reversed definition:
 318         *      0 for positive, 1 for negative */
 319        if (get_reg_field_value(pol_value,
 320                        CRTC0_CRTC_V_SYNC_A_CNTL,
 321                        CRTC_V_SYNC_A_POL) == 0) {
 322                rising_edge = 1;
 323        } else {
 324                falling_edge = 1;
 325        }
 326
 327        /* TODO What about other sources ?*/
 328        trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0;
 329
 330        CRTC_REG_UPDATE_N(CRTC0_CRTC_TRIGB_CNTL, 7,
 331                FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT), trig_src_select,
 332                FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT), TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
 333                FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL), rising_edge,
 334                FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL), falling_edge,
 335                /* send every signal */
 336                FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT), 0,
 337                /* no delay */
 338                FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY), 0,
 339                /* clear trigger status */
 340                FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR), 1);
 341
 342        CRTC_REG_UPDATE_3(
 343                        CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
 344                        CRTC_FORCE_COUNT_NOW_MODE, 2,
 345                        CRTC_FORCE_COUNT_NOW_TRIG_SEL, 1,
 346                        CRTC_FORCE_COUNT_NOW_CLEAR, 1);
 347}
 348
 349/* disabling trigger-reset */
 350void dce120_timing_generator_disable_reset_trigger(
 351        struct timing_generator *tg)
 352{
 353        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 354
 355        CRTC_REG_UPDATE_2(
 356                CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
 357                CRTC_FORCE_COUNT_NOW_MODE, 0,
 358                CRTC_FORCE_COUNT_NOW_CLEAR, 1);
 359
 360        CRTC_REG_UPDATE_3(
 361                CRTC0_CRTC_TRIGB_CNTL,
 362                CRTC_TRIGB_SOURCE_SELECT, TRIGGER_SOURCE_SELECT_LOGIC_ZERO,
 363                CRTC_TRIGB_POLARITY_SELECT, TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
 364                /* clear trigger status */
 365                CRTC_TRIGB_CLEAR, 1);
 366
 367}
 368
 369/* Checks whether CRTC triggered reset occurred */
 370bool dce120_timing_generator_did_triggered_reset_occur(
 371        struct timing_generator *tg)
 372{
 373        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 374        uint32_t value = dm_read_reg_soc15(
 375                        tg->ctx,
 376                        mmCRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
 377                        tg110->offsets.crtc);
 378
 379        return get_reg_field_value(value,
 380                        CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
 381                        CRTC_FORCE_COUNT_NOW_OCCURRED) != 0;
 382}
 383
 384
 385/******** Stuff to move to other virtual HW objects *****************/
 386/* Move to enable accelerated mode */
 387void dce120_timing_generator_disable_vga(struct timing_generator *tg)
 388{
 389        uint32_t offset = 0;
 390        uint32_t value = 0;
 391        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 392
 393        switch (tg110->controller_id) {
 394        case CONTROLLER_ID_D0:
 395                offset = 0;
 396                break;
 397        case CONTROLLER_ID_D1:
 398                offset = mmD2VGA_CONTROL - mmD1VGA_CONTROL;
 399                break;
 400        case CONTROLLER_ID_D2:
 401                offset = mmD3VGA_CONTROL - mmD1VGA_CONTROL;
 402                break;
 403        case CONTROLLER_ID_D3:
 404                offset = mmD4VGA_CONTROL - mmD1VGA_CONTROL;
 405                break;
 406        case CONTROLLER_ID_D4:
 407                offset = mmD5VGA_CONTROL - mmD1VGA_CONTROL;
 408                break;
 409        case CONTROLLER_ID_D5:
 410                offset = mmD6VGA_CONTROL - mmD1VGA_CONTROL;
 411                break;
 412        default:
 413                break;
 414        }
 415
 416        value = dm_read_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset);
 417
 418        set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE);
 419        set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT);
 420        set_reg_field_value(
 421                        value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT);
 422        set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN);
 423
 424        dm_write_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset, value);
 425}
 426/* TODO: Should we move it to transform */
 427/* Fully program CRTC timing in timing generator */
 428void dce120_timing_generator_program_blanking(
 429        struct timing_generator *tg,
 430        const struct dc_crtc_timing *timing)
 431{
 432        uint32_t tmp1 = 0;
 433        uint32_t tmp2 = 0;
 434        uint32_t vsync_offset = timing->v_border_bottom +
 435                        timing->v_front_porch;
 436        uint32_t v_sync_start = timing->v_addressable + vsync_offset;
 437
 438        uint32_t hsync_offset = timing->h_border_right +
 439                        timing->h_front_porch;
 440        uint32_t h_sync_start = timing->h_addressable + hsync_offset;
 441        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 442
 443        CRTC_REG_UPDATE(
 444                CRTC0_CRTC_H_TOTAL,
 445                CRTC_H_TOTAL,
 446                timing->h_total - 1);
 447
 448        CRTC_REG_UPDATE(
 449                CRTC0_CRTC_V_TOTAL,
 450                CRTC_V_TOTAL,
 451                timing->v_total - 1);
 452
 453        /* In case of V_TOTAL_CONTROL is on, make sure V_TOTAL_MAX and
 454         * V_TOTAL_MIN are equal to V_TOTAL.
 455         */
 456        CRTC_REG_UPDATE(
 457                CRTC0_CRTC_V_TOTAL_MAX,
 458                CRTC_V_TOTAL_MAX,
 459                timing->v_total - 1);
 460
 461        CRTC_REG_UPDATE(
 462                CRTC0_CRTC_V_TOTAL_MIN,
 463                CRTC_V_TOTAL_MIN,
 464                timing->v_total - 1);
 465
 466        tmp1 = timing->h_total -
 467                        (h_sync_start + timing->h_border_left);
 468        tmp2 = tmp1 + timing->h_addressable +
 469                        timing->h_border_left + timing->h_border_right;
 470
 471        CRTC_REG_UPDATE_2(
 472                        CRTC0_CRTC_H_BLANK_START_END,
 473                        CRTC_H_BLANK_END, tmp1,
 474                        CRTC_H_BLANK_START, tmp2);
 475
 476        tmp1 = timing->v_total - (v_sync_start + timing->v_border_top);
 477        tmp2 = tmp1 + timing->v_addressable + timing->v_border_top +
 478                        timing->v_border_bottom;
 479
 480        CRTC_REG_UPDATE_2(
 481                CRTC0_CRTC_V_BLANK_START_END,
 482                CRTC_V_BLANK_END, tmp1,
 483                CRTC_V_BLANK_START, tmp2);
 484}
 485
 486/* TODO: Should we move it to opp? */
 487/* Combine with below and move YUV/RGB color conversion to SW layer */
 488void dce120_timing_generator_program_blank_color(
 489        struct timing_generator *tg,
 490        const struct tg_color *black_color)
 491{
 492        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 493
 494        CRTC_REG_UPDATE_3(
 495                CRTC0_CRTC_BLACK_COLOR,
 496                CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb,
 497                CRTC_BLACK_COLOR_G_Y, black_color->color_g_y,
 498                CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr);
 499}
 500/* Combine with above and move YUV/RGB color conversion to SW layer */
 501void dce120_timing_generator_set_overscan_color_black(
 502        struct timing_generator *tg,
 503        const struct tg_color *color)
 504{
 505        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 506        uint32_t value = 0;
 507        CRTC_REG_SET_3(
 508                CRTC0_CRTC_OVERSCAN_COLOR,
 509                CRTC_OVERSCAN_COLOR_BLUE, color->color_b_cb,
 510                CRTC_OVERSCAN_COLOR_GREEN, color->color_g_y,
 511                CRTC_OVERSCAN_COLOR_RED, color->color_r_cr);
 512
 513        value = dm_read_reg_soc15(
 514                        tg->ctx,
 515                        mmCRTC0_CRTC_OVERSCAN_COLOR,
 516                        tg110->offsets.crtc);
 517
 518        dm_write_reg_soc15(
 519                        tg->ctx,
 520                        mmCRTC0_CRTC_BLACK_COLOR,
 521                        tg110->offsets.crtc,
 522                        value);
 523
 524        /* This is desirable to have a constant DAC output voltage during the
 525         * blank time that is higher than the 0 volt reference level that the
 526         * DAC outputs when the NBLANK signal
 527         * is asserted low, such as for output to an analog TV. */
 528        dm_write_reg_soc15(
 529                tg->ctx,
 530                mmCRTC0_CRTC_BLANK_DATA_COLOR,
 531                tg110->offsets.crtc,
 532                value);
 533
 534        /* TO DO we have to program EXT registers and we need to know LB DATA
 535         * format because it is used when more 10 , i.e. 12 bits per color
 536         *
 537         * m_mmDxCRTC_OVERSCAN_COLOR_EXT
 538         * m_mmDxCRTC_BLACK_COLOR_EXT
 539         * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
 540         */
 541}
 542
 543void dce120_timing_generator_set_drr(
 544        struct timing_generator *tg,
 545        const struct drr_params *params)
 546{
 547
 548        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 549
 550        if (params != NULL &&
 551                params->vertical_total_max > 0 &&
 552                params->vertical_total_min > 0) {
 553
 554                CRTC_REG_UPDATE(
 555                                CRTC0_CRTC_V_TOTAL_MIN,
 556                                CRTC_V_TOTAL_MIN, params->vertical_total_min - 1);
 557                CRTC_REG_UPDATE(
 558                                CRTC0_CRTC_V_TOTAL_MAX,
 559                                CRTC_V_TOTAL_MAX, params->vertical_total_max - 1);
 560                CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 6,
 561                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 1,
 562                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 1,
 563                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0,
 564                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0,
 565                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK_EN), 0,
 566                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0);
 567                CRTC_REG_UPDATE(
 568                                CRTC0_CRTC_STATIC_SCREEN_CONTROL,
 569                                CRTC_STATIC_SCREEN_EVENT_MASK,
 570                                0x180);
 571
 572        } else {
 573                CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 5,
 574                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 0,
 575                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 0,
 576                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0,
 577                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0,
 578                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0);
 579                CRTC_REG_UPDATE(
 580                                CRTC0_CRTC_V_TOTAL_MIN,
 581                                CRTC_V_TOTAL_MIN, 0);
 582                CRTC_REG_UPDATE(
 583                                CRTC0_CRTC_V_TOTAL_MAX,
 584                                CRTC_V_TOTAL_MAX, 0);
 585                CRTC_REG_UPDATE(
 586                                CRTC0_CRTC_STATIC_SCREEN_CONTROL,
 587                                CRTC_STATIC_SCREEN_EVENT_MASK,
 588                                0);
 589        }
 590}
 591
 592/**
 593 *****************************************************************************
 594 *  Function: dce120_timing_generator_get_position
 595 *
 596 *  @brief
 597 *     Returns CRTC vertical/horizontal counters
 598 *
 599 *  @param [out] position
 600 *****************************************************************************
 601 */
 602void dce120_timing_generator_get_position(struct timing_generator *tg,
 603        struct crtc_position *position)
 604{
 605        uint32_t value;
 606        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 607
 608        value = dm_read_reg_soc15(
 609                        tg->ctx,
 610                        mmCRTC0_CRTC_STATUS_POSITION,
 611                        tg110->offsets.crtc);
 612
 613        position->horizontal_count = get_reg_field_value(
 614                        value,
 615                        CRTC0_CRTC_STATUS_POSITION,
 616                        CRTC_HORZ_COUNT);
 617
 618        position->vertical_count = get_reg_field_value(
 619                        value,
 620                        CRTC0_CRTC_STATUS_POSITION,
 621                        CRTC_VERT_COUNT);
 622
 623        value = dm_read_reg_soc15(
 624                        tg->ctx,
 625                        mmCRTC0_CRTC_NOM_VERT_POSITION,
 626                        tg110->offsets.crtc);
 627
 628        position->nominal_vcount = get_reg_field_value(
 629                        value,
 630                        CRTC0_CRTC_NOM_VERT_POSITION,
 631                        CRTC_VERT_COUNT_NOM);
 632}
 633
 634
 635void dce120_timing_generator_get_crtc_scanoutpos(
 636        struct timing_generator *tg,
 637        uint32_t *v_blank_start,
 638        uint32_t *v_blank_end,
 639        uint32_t *h_position,
 640        uint32_t *v_position)
 641{
 642        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 643        struct crtc_position position;
 644
 645        uint32_t v_blank_start_end = dm_read_reg_soc15(
 646                        tg->ctx,
 647                        mmCRTC0_CRTC_V_BLANK_START_END,
 648                        tg110->offsets.crtc);
 649
 650        *v_blank_start = get_reg_field_value(v_blank_start_end,
 651                                             CRTC0_CRTC_V_BLANK_START_END,
 652                                             CRTC_V_BLANK_START);
 653        *v_blank_end = get_reg_field_value(v_blank_start_end,
 654                                           CRTC0_CRTC_V_BLANK_START_END,
 655                                           CRTC_V_BLANK_END);
 656
 657        dce120_timing_generator_get_crtc_position(
 658                        tg, &position);
 659
 660        *h_position = position.horizontal_count;
 661        *v_position = position.vertical_count;
 662}
 663
 664void dce120_timing_generator_enable_advanced_request(
 665        struct timing_generator *tg,
 666        bool enable,
 667        const struct dc_crtc_timing *timing)
 668{
 669        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 670        uint32_t v_sync_width_and_b_porch =
 671                                timing->v_total - timing->v_addressable -
 672                                timing->v_border_bottom - timing->v_front_porch;
 673        uint32_t value = dm_read_reg_soc15(
 674                                tg->ctx,
 675                                mmCRTC0_CRTC_START_LINE_CONTROL,
 676                                tg110->offsets.crtc);
 677
 678        set_reg_field_value(
 679                value,
 680                enable ? 0 : 1,
 681                CRTC0_CRTC_START_LINE_CONTROL,
 682                CRTC_LEGACY_REQUESTOR_EN);
 683
 684        /* Program advanced line position acc.to the best case from fetching data perspective to hide MC latency
 685         * and prefilling Line Buffer in V Blank (to 10 lines as LB can store max 10 lines)
 686         */
 687        if (v_sync_width_and_b_porch > 10)
 688                v_sync_width_and_b_porch = 10;
 689
 690        set_reg_field_value(
 691                value,
 692                v_sync_width_and_b_porch,
 693                CRTC0_CRTC_START_LINE_CONTROL,
 694                CRTC_ADVANCED_START_LINE_POSITION);
 695
 696        dm_write_reg_soc15(tg->ctx,
 697                        mmCRTC0_CRTC_START_LINE_CONTROL,
 698                        tg110->offsets.crtc,
 699                        value);
 700}
 701
 702void dce120_tg_program_blank_color(struct timing_generator *tg,
 703        const struct tg_color *black_color)
 704{
 705        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 706        uint32_t value = 0;
 707
 708        CRTC_REG_UPDATE_3(
 709                CRTC0_CRTC_BLACK_COLOR,
 710                CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb,
 711                CRTC_BLACK_COLOR_G_Y, black_color->color_g_y,
 712                CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr);
 713
 714        value = dm_read_reg_soc15(
 715                                tg->ctx,
 716                                mmCRTC0_CRTC_BLACK_COLOR,
 717                                tg110->offsets.crtc);
 718        dm_write_reg_soc15(
 719                tg->ctx,
 720                mmCRTC0_CRTC_BLANK_DATA_COLOR,
 721                tg110->offsets.crtc,
 722                value);
 723}
 724
 725void dce120_tg_set_overscan_color(struct timing_generator *tg,
 726        const struct tg_color *overscan_color)
 727{
 728        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 729
 730        CRTC_REG_SET_3(
 731                CRTC0_CRTC_OVERSCAN_COLOR,
 732                CRTC_OVERSCAN_COLOR_BLUE, overscan_color->color_b_cb,
 733                CRTC_OVERSCAN_COLOR_GREEN, overscan_color->color_g_y,
 734                CRTC_OVERSCAN_COLOR_RED, overscan_color->color_r_cr);
 735}
 736
 737static void dce120_tg_program_timing(struct timing_generator *tg,
 738        const struct dc_crtc_timing *timing,
 739        int vready_offset,
 740        int vstartup_start,
 741        int vupdate_offset,
 742        int vupdate_width,
 743        const enum signal_type signal,
 744        bool use_vbios)
 745{
 746        if (use_vbios)
 747                dce110_timing_generator_program_timing_generator(tg, timing);
 748        else
 749                dce120_timing_generator_program_blanking(tg, timing);
 750}
 751
 752bool dce120_tg_is_blanked(struct timing_generator *tg)
 753{
 754        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 755        uint32_t value = dm_read_reg_soc15(
 756                        tg->ctx,
 757                        mmCRTC0_CRTC_BLANK_CONTROL,
 758                        tg110->offsets.crtc);
 759
 760        if (get_reg_field_value(
 761                value,
 762                CRTC0_CRTC_BLANK_CONTROL,
 763                CRTC_BLANK_DATA_EN) == 1 &&
 764            get_reg_field_value(
 765                value,
 766                CRTC0_CRTC_BLANK_CONTROL,
 767                CRTC_CURRENT_BLANK_STATE) == 1)
 768                        return true;
 769
 770        return false;
 771}
 772
 773void dce120_tg_set_blank(struct timing_generator *tg,
 774                bool enable_blanking)
 775{
 776        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 777
 778        CRTC_REG_SET(
 779                CRTC0_CRTC_DOUBLE_BUFFER_CONTROL,
 780                CRTC_BLANK_DATA_DOUBLE_BUFFER_EN, 1);
 781
 782        if (enable_blanking)
 783                CRTC_REG_SET(CRTC0_CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1);
 784        else
 785                dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_BLANK_CONTROL,
 786                        tg110->offsets.crtc, 0);
 787}
 788
 789bool dce120_tg_validate_timing(struct timing_generator *tg,
 790        const struct dc_crtc_timing *timing);
 791
 792void dce120_tg_wait_for_state(struct timing_generator *tg,
 793        enum crtc_state state)
 794{
 795        switch (state) {
 796        case CRTC_STATE_VBLANK:
 797                dce120_timing_generator_wait_for_vblank(tg);
 798                break;
 799
 800        case CRTC_STATE_VACTIVE:
 801                dce120_timing_generator_wait_for_vactive(tg);
 802                break;
 803
 804        default:
 805                break;
 806        }
 807}
 808
 809void dce120_tg_set_colors(struct timing_generator *tg,
 810        const struct tg_color *blank_color,
 811        const struct tg_color *overscan_color)
 812{
 813        if (blank_color != NULL)
 814                dce120_tg_program_blank_color(tg, blank_color);
 815
 816        if (overscan_color != NULL)
 817                dce120_tg_set_overscan_color(tg, overscan_color);
 818}
 819
 820static void dce120_timing_generator_set_static_screen_control(
 821        struct timing_generator *tg,
 822        uint32_t event_triggers,
 823        uint32_t num_frames)
 824{
 825        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 826
 827        // By register spec, it only takes 8 bit value
 828        if (num_frames > 0xFF)
 829                num_frames = 0xFF;
 830
 831        CRTC_REG_UPDATE_2(CRTC0_CRTC_STATIC_SCREEN_CONTROL,
 832                        CRTC_STATIC_SCREEN_EVENT_MASK, event_triggers,
 833                        CRTC_STATIC_SCREEN_FRAME_COUNT, num_frames);
 834}
 835
 836void dce120_timing_generator_set_test_pattern(
 837        struct timing_generator *tg,
 838        /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
 839         * because this is not DP-specific (which is probably somewhere in DP
 840         * encoder) */
 841        enum controller_dp_test_pattern test_pattern,
 842        enum dc_color_depth color_depth)
 843{
 844        struct dc_context *ctx = tg->ctx;
 845        uint32_t value;
 846        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 847        enum test_pattern_color_format bit_depth;
 848        enum test_pattern_dyn_range dyn_range;
 849        enum test_pattern_mode mode;
 850        /* color ramp generator mixes 16-bits color */
 851        uint32_t src_bpc = 16;
 852        /* requested bpc */
 853        uint32_t dst_bpc;
 854        uint32_t index;
 855        /* RGB values of the color bars.
 856         * Produce two RGB colors: RGB0 - white (all Fs)
 857         * and RGB1 - black (all 0s)
 858         * (three RGB components for two colors)
 859         */
 860        uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
 861                                                0x0000, 0x0000};
 862        /* dest color (converted to the specified color format) */
 863        uint16_t dst_color[6];
 864        uint32_t inc_base;
 865
 866        /* translate to bit depth */
 867        switch (color_depth) {
 868        case COLOR_DEPTH_666:
 869                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
 870        break;
 871        case COLOR_DEPTH_888:
 872                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 873        break;
 874        case COLOR_DEPTH_101010:
 875                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
 876        break;
 877        case COLOR_DEPTH_121212:
 878                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
 879        break;
 880        default:
 881                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 882        break;
 883        }
 884
 885        switch (test_pattern) {
 886        case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
 887        case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
 888        {
 889                dyn_range = (test_pattern ==
 890                                CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
 891                                TEST_PATTERN_DYN_RANGE_CEA :
 892                                TEST_PATTERN_DYN_RANGE_VESA);
 893                mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
 894
 895                CRTC_REG_UPDATE_2(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
 896                                CRTC_TEST_PATTERN_VRES, 6,
 897                                CRTC_TEST_PATTERN_HRES, 6);
 898
 899                CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
 900                                CRTC_TEST_PATTERN_EN, 1,
 901                                CRTC_TEST_PATTERN_MODE, mode,
 902                                CRTC_TEST_PATTERN_DYNAMIC_RANGE, dyn_range,
 903                                CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
 904        }
 905        break;
 906
 907        case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
 908        case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
 909        {
 910                mode = (test_pattern ==
 911                        CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
 912                        TEST_PATTERN_MODE_VERTICALBARS :
 913                        TEST_PATTERN_MODE_HORIZONTALBARS);
 914
 915                switch (bit_depth) {
 916                case TEST_PATTERN_COLOR_FORMAT_BPC_6:
 917                        dst_bpc = 6;
 918                break;
 919                case TEST_PATTERN_COLOR_FORMAT_BPC_8:
 920                        dst_bpc = 8;
 921                break;
 922                case TEST_PATTERN_COLOR_FORMAT_BPC_10:
 923                        dst_bpc = 10;
 924                break;
 925                default:
 926                        dst_bpc = 8;
 927                break;
 928                }
 929
 930                /* adjust color to the required colorFormat */
 931                for (index = 0; index < 6; index++) {
 932                        /* dst = 2^dstBpc * src / 2^srcBpc = src >>
 933                         * (srcBpc - dstBpc);
 934                         */
 935                        dst_color[index] =
 936                                src_color[index] >> (src_bpc - dst_bpc);
 937                /* CRTC_TEST_PATTERN_DATA has 16 bits,
 938                 * lowest 6 are hardwired to ZERO
 939                 * color bits should be left aligned aligned to MSB
 940                 * XXXXXXXXXX000000 for 10 bit,
 941                 * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
 942                 */
 943                        dst_color[index] <<= (16 - dst_bpc);
 944                }
 945
 946                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, 0);
 947
 948                /* We have to write the mask before data, similar to pipeline.
 949                 * For example, for 8 bpc, if we want RGB0 to be magenta,
 950                 * and RGB1 to be cyan,
 951                 * we need to make 7 writes:
 952                 * MASK   DATA
 953                 * 000001 00000000 00000000                     set mask to R0
 954                 * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
 955                 * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
 956                 * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
 957                 * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
 958                 * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
 959                 * 100000 11111111 00000000     B1 255, 0xFF00
 960                 *
 961                 * we will make a loop of 6 in which we prepare the mask,
 962                 * then write, then prepare the color for next write.
 963                 * first iteration will write mask only,
 964                 * but each next iteration color prepared in
 965                 * previous iteration will be written within new mask,
 966                 * the last component will written separately,
 967                 * mask is not changing between 6th and 7th write
 968                 * and color will be prepared by last iteration
 969                 */
 970
 971                /* write color, color values mask in CRTC_TEST_PATTERN_MASK
 972                 * is B1, G1, R1, B0, G0, R0
 973                 */
 974                value = 0;
 975                for (index = 0; index < 6; index++) {
 976                        /* prepare color mask, first write PATTERN_DATA
 977                         * will have all zeros
 978                         */
 979                        set_reg_field_value(
 980                                value,
 981                                (1 << index),
 982                                CRTC0_CRTC_TEST_PATTERN_COLOR,
 983                                CRTC_TEST_PATTERN_MASK);
 984                        /* write color component */
 985                        dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
 986                        /* prepare next color component,
 987                         * will be written in the next iteration
 988                         */
 989                        set_reg_field_value(
 990                                value,
 991                                dst_color[index],
 992                                CRTC0_CRTC_TEST_PATTERN_COLOR,
 993                                CRTC_TEST_PATTERN_DATA);
 994                }
 995                /* write last color component,
 996                 * it's been already prepared in the loop
 997                 */
 998                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
 999
1000                /* enable test pattern */
1001                CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
1002                                CRTC_TEST_PATTERN_EN, 1,
1003                                CRTC_TEST_PATTERN_MODE, mode,
1004                                CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
1005                                CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1006        }
1007        break;
1008
1009        case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
1010        {
1011                mode = (bit_depth ==
1012                        TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
1013                        TEST_PATTERN_MODE_DUALRAMP_RGB :
1014                        TEST_PATTERN_MODE_SINGLERAMP_RGB);
1015
1016                switch (bit_depth) {
1017                case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1018                        dst_bpc = 6;
1019                break;
1020                case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1021                        dst_bpc = 8;
1022                break;
1023                case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1024                        dst_bpc = 10;
1025                break;
1026                default:
1027                        dst_bpc = 8;
1028                break;
1029                }
1030
1031                /* increment for the first ramp for one color gradation
1032                 * 1 gradation for 6-bit color is 2^10
1033                 * gradations in 16-bit color
1034                 */
1035                inc_base = (src_bpc - dst_bpc);
1036
1037                switch (bit_depth) {
1038                case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1039                {
1040                        CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1041                                        CRTC_TEST_PATTERN_INC0, inc_base,
1042                                        CRTC_TEST_PATTERN_INC1, 0,
1043                                        CRTC_TEST_PATTERN_HRES, 6,
1044                                        CRTC_TEST_PATTERN_VRES, 6,
1045                                        CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1046                }
1047                break;
1048                case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1049                {
1050                        CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1051                                        CRTC_TEST_PATTERN_INC0, inc_base,
1052                                        CRTC_TEST_PATTERN_INC1, 0,
1053                                        CRTC_TEST_PATTERN_HRES, 8,
1054                                        CRTC_TEST_PATTERN_VRES, 6,
1055                                        CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1056                }
1057                break;
1058                case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1059                {
1060                        CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1061                                        CRTC_TEST_PATTERN_INC0, inc_base,
1062                                        CRTC_TEST_PATTERN_INC1, inc_base + 2,
1063                                        CRTC_TEST_PATTERN_HRES, 8,
1064                                        CRTC_TEST_PATTERN_VRES, 5,
1065                                        CRTC_TEST_PATTERN_RAMP0_OFFSET, 384 << 6);
1066                }
1067                break;
1068                default:
1069                break;
1070                }
1071
1072                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, 0);
1073
1074                /* enable test pattern */
1075                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, 0);
1076
1077                CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
1078                                CRTC_TEST_PATTERN_EN, 1,
1079                                CRTC_TEST_PATTERN_MODE, mode,
1080                                CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
1081                                CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1082        }
1083        break;
1084        case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1085        {
1086                value = 0;
1087                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc,  value);
1088                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
1089                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, value);
1090        }
1091        break;
1092        default:
1093        break;
1094        }
1095}
1096
1097static bool dce120_arm_vert_intr(
1098                struct timing_generator *tg,
1099                uint8_t width)
1100{
1101        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1102        uint32_t v_blank_start, v_blank_end, h_position, v_position;
1103
1104        tg->funcs->get_scanoutpos(
1105                                tg,
1106                                &v_blank_start,
1107                                &v_blank_end,
1108                                &h_position,
1109                                &v_position);
1110
1111        if (v_blank_start == 0 || v_blank_end == 0)
1112                return false;
1113
1114        CRTC_REG_SET_2(
1115                        CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION,
1116                        CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start,
1117                        CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width);
1118
1119        return true;
1120}
1121
1122
1123static bool dce120_is_tg_enabled(struct timing_generator *tg)
1124{
1125        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1126        uint32_t value, field;
1127
1128        value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CONTROL,
1129                                  tg110->offsets.crtc);
1130        field = get_reg_field_value(value, CRTC0_CRTC_CONTROL,
1131                                    CRTC_CURRENT_MASTER_EN_STATE);
1132
1133        return field == 1;
1134}
1135
1136static bool dce120_configure_crc(struct timing_generator *tg,
1137                                 const struct crc_params *params)
1138{
1139        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1140
1141        /* Cannot configure crc on a CRTC that is disabled */
1142        if (!dce120_is_tg_enabled(tg))
1143                return false;
1144
1145        /* First, disable CRC before we configure it. */
1146        dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1147                           tg110->offsets.crtc, 0);
1148
1149        if (!params->enable)
1150                return true;
1151
1152        /* Program frame boundaries */
1153        /* Window A x axis start and end. */
1154        CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_X_CONTROL,
1155                          CRTC_CRC0_WINDOWA_X_START, params->windowa_x_start,
1156                          CRTC_CRC0_WINDOWA_X_END, params->windowa_x_end);
1157
1158        /* Window A y axis start and end. */
1159        CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_Y_CONTROL,
1160                          CRTC_CRC0_WINDOWA_Y_START, params->windowa_y_start,
1161                          CRTC_CRC0_WINDOWA_Y_END, params->windowa_y_end);
1162
1163        /* Window B x axis start and end. */
1164        CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_X_CONTROL,
1165                          CRTC_CRC0_WINDOWB_X_START, params->windowb_x_start,
1166                          CRTC_CRC0_WINDOWB_X_END, params->windowb_x_end);
1167
1168        /* Window B y axis start and end. */
1169        CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_Y_CONTROL,
1170                          CRTC_CRC0_WINDOWB_Y_START, params->windowb_y_start,
1171                          CRTC_CRC0_WINDOWB_Y_END, params->windowb_y_end);
1172
1173        /* Set crc mode and selection, and enable. Only using CRC0*/
1174        CRTC_REG_UPDATE_3(CRTC0_CRTC_CRC_CNTL,
1175                          CRTC_CRC_EN, params->continuous_mode ? 1 : 0,
1176                          CRTC_CRC0_SELECT, params->selection,
1177                          CRTC_CRC_EN, 1);
1178
1179        return true;
1180}
1181
1182static bool dce120_get_crc(struct timing_generator *tg, uint32_t *r_cr,
1183                           uint32_t *g_y, uint32_t *b_cb)
1184{
1185        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1186        uint32_t value, field;
1187
1188        value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1189                                  tg110->offsets.crtc);
1190        field = get_reg_field_value(value, CRTC0_CRTC_CRC_CNTL, CRTC_CRC_EN);
1191
1192        /* Early return if CRC is not enabled for this CRTC */
1193        if (!field)
1194                return false;
1195
1196        value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_RG,
1197                                  tg110->offsets.crtc);
1198        *r_cr = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_R_CR);
1199        *g_y = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_G_Y);
1200
1201        value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_B,
1202                                  tg110->offsets.crtc);
1203        *b_cb = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_B, CRC0_B_CB);
1204
1205        return true;
1206}
1207
1208static const struct timing_generator_funcs dce120_tg_funcs = {
1209                .validate_timing = dce120_tg_validate_timing,
1210                .program_timing = dce120_tg_program_timing,
1211                .enable_crtc = dce120_timing_generator_enable_crtc,
1212                .disable_crtc = dce110_timing_generator_disable_crtc,
1213                /* used by enable_timing_synchronization. Not need for FPGA */
1214                .is_counter_moving = dce110_timing_generator_is_counter_moving,
1215                /* never be called */
1216                .get_position = dce120_timing_generator_get_crtc_position,
1217                .get_frame_count = dce120_timing_generator_get_vblank_counter,
1218                .get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos,
1219                .set_early_control = dce120_timing_generator_set_early_control,
1220                /* used by enable_timing_synchronization. Not need for FPGA */
1221                .wait_for_state = dce120_tg_wait_for_state,
1222                .set_blank = dce120_tg_set_blank,
1223                .is_blanked = dce120_tg_is_blanked,
1224                /* never be called */
1225                .set_colors = dce120_tg_set_colors,
1226                .set_overscan_blank_color = dce120_timing_generator_set_overscan_color_black,
1227                .set_blank_color = dce120_timing_generator_program_blank_color,
1228                .disable_vga = dce120_timing_generator_disable_vga,
1229                .did_triggered_reset_occur = dce120_timing_generator_did_triggered_reset_occur,
1230                .setup_global_swap_lock = dce120_timing_generator_setup_global_swap_lock,
1231                .enable_reset_trigger = dce120_timing_generator_enable_reset_trigger,
1232                .disable_reset_trigger = dce120_timing_generator_disable_reset_trigger,
1233                .tear_down_global_swap_lock = dce120_timing_generator_tear_down_global_swap_lock,
1234                .enable_advanced_request = dce120_timing_generator_enable_advanced_request,
1235                .set_drr = dce120_timing_generator_set_drr,
1236                .set_static_screen_control = dce120_timing_generator_set_static_screen_control,
1237                .set_test_pattern = dce120_timing_generator_set_test_pattern,
1238                .arm_vert_intr = dce120_arm_vert_intr,
1239                .is_tg_enabled = dce120_is_tg_enabled,
1240                .configure_crc = dce120_configure_crc,
1241                .get_crc = dce120_get_crc,
1242};
1243
1244
1245void dce120_timing_generator_construct(
1246        struct dce110_timing_generator *tg110,
1247        struct dc_context *ctx,
1248        uint32_t instance,
1249        const struct dce110_timing_generator_offsets *offsets)
1250{
1251        tg110->controller_id = CONTROLLER_ID_D0 + instance;
1252        tg110->base.inst = instance;
1253
1254        tg110->offsets = *offsets;
1255
1256        tg110->base.funcs = &dce120_tg_funcs;
1257
1258        tg110->base.ctx = ctx;
1259        tg110->base.bp = ctx->dc_bios;
1260
1261        tg110->max_h_total = CRTC0_CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
1262        tg110->max_v_total = CRTC0_CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
1263
1264        /*//CRTC requires a minimum HBLANK = 32 pixels and o
1265         * Minimum HSYNC = 8 pixels*/
1266        tg110->min_h_blank = 32;
1267        /*DCE12_CRTC_Block_ARch.doc*/
1268        tg110->min_h_front_porch = 0;
1269        tg110->min_h_back_porch = 0;
1270
1271        tg110->min_h_sync_width = 4;
1272        tg110->min_v_sync_width = 1;
1273        tg110->min_v_blank = 3;
1274}
1275