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 */
 101static bool 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
 128static bool 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 */
 136static bool 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
 156static void 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 */
 169static uint32_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 */
 184static void 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 */
 210static void 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 */
 232static void 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*/
 245static void 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 */
 282static void 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 */
 303static void 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 */
 350static void 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 */
 370static bool 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 */
 387static void 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 */
 428static void 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 */
 488static void 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 */
 501static void 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
 543static void 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
 592static void dce120_timing_generator_get_crtc_scanoutpos(
 593        struct timing_generator *tg,
 594        uint32_t *v_blank_start,
 595        uint32_t *v_blank_end,
 596        uint32_t *h_position,
 597        uint32_t *v_position)
 598{
 599        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 600        struct crtc_position position;
 601
 602        uint32_t v_blank_start_end = dm_read_reg_soc15(
 603                        tg->ctx,
 604                        mmCRTC0_CRTC_V_BLANK_START_END,
 605                        tg110->offsets.crtc);
 606
 607        *v_blank_start = get_reg_field_value(v_blank_start_end,
 608                                             CRTC0_CRTC_V_BLANK_START_END,
 609                                             CRTC_V_BLANK_START);
 610        *v_blank_end = get_reg_field_value(v_blank_start_end,
 611                                           CRTC0_CRTC_V_BLANK_START_END,
 612                                           CRTC_V_BLANK_END);
 613
 614        dce120_timing_generator_get_crtc_position(
 615                        tg, &position);
 616
 617        *h_position = position.horizontal_count;
 618        *v_position = position.vertical_count;
 619}
 620
 621static void dce120_timing_generator_enable_advanced_request(
 622        struct timing_generator *tg,
 623        bool enable,
 624        const struct dc_crtc_timing *timing)
 625{
 626        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 627        uint32_t v_sync_width_and_b_porch =
 628                                timing->v_total - timing->v_addressable -
 629                                timing->v_border_bottom - timing->v_front_porch;
 630        uint32_t value = dm_read_reg_soc15(
 631                                tg->ctx,
 632                                mmCRTC0_CRTC_START_LINE_CONTROL,
 633                                tg110->offsets.crtc);
 634
 635        set_reg_field_value(
 636                value,
 637                enable ? 0 : 1,
 638                CRTC0_CRTC_START_LINE_CONTROL,
 639                CRTC_LEGACY_REQUESTOR_EN);
 640
 641        /* Program advanced line position acc.to the best case from fetching data perspective to hide MC latency
 642         * and prefilling Line Buffer in V Blank (to 10 lines as LB can store max 10 lines)
 643         */
 644        if (v_sync_width_and_b_porch > 10)
 645                v_sync_width_and_b_porch = 10;
 646
 647        set_reg_field_value(
 648                value,
 649                v_sync_width_and_b_porch,
 650                CRTC0_CRTC_START_LINE_CONTROL,
 651                CRTC_ADVANCED_START_LINE_POSITION);
 652
 653        dm_write_reg_soc15(tg->ctx,
 654                        mmCRTC0_CRTC_START_LINE_CONTROL,
 655                        tg110->offsets.crtc,
 656                        value);
 657}
 658
 659static void dce120_tg_program_blank_color(struct timing_generator *tg,
 660        const struct tg_color *black_color)
 661{
 662        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 663        uint32_t value = 0;
 664
 665        CRTC_REG_UPDATE_3(
 666                CRTC0_CRTC_BLACK_COLOR,
 667                CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb,
 668                CRTC_BLACK_COLOR_G_Y, black_color->color_g_y,
 669                CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr);
 670
 671        value = dm_read_reg_soc15(
 672                                tg->ctx,
 673                                mmCRTC0_CRTC_BLACK_COLOR,
 674                                tg110->offsets.crtc);
 675        dm_write_reg_soc15(
 676                tg->ctx,
 677                mmCRTC0_CRTC_BLANK_DATA_COLOR,
 678                tg110->offsets.crtc,
 679                value);
 680}
 681
 682static void dce120_tg_set_overscan_color(struct timing_generator *tg,
 683        const struct tg_color *overscan_color)
 684{
 685        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 686
 687        CRTC_REG_SET_3(
 688                CRTC0_CRTC_OVERSCAN_COLOR,
 689                CRTC_OVERSCAN_COLOR_BLUE, overscan_color->color_b_cb,
 690                CRTC_OVERSCAN_COLOR_GREEN, overscan_color->color_g_y,
 691                CRTC_OVERSCAN_COLOR_RED, overscan_color->color_r_cr);
 692}
 693
 694static void dce120_tg_program_timing(struct timing_generator *tg,
 695        const struct dc_crtc_timing *timing,
 696        int vready_offset,
 697        int vstartup_start,
 698        int vupdate_offset,
 699        int vupdate_width,
 700        const enum signal_type signal,
 701        bool use_vbios)
 702{
 703        if (use_vbios)
 704                dce110_timing_generator_program_timing_generator(tg, timing);
 705        else
 706                dce120_timing_generator_program_blanking(tg, timing);
 707}
 708
 709static bool dce120_tg_is_blanked(struct timing_generator *tg)
 710{
 711        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 712        uint32_t value = dm_read_reg_soc15(
 713                        tg->ctx,
 714                        mmCRTC0_CRTC_BLANK_CONTROL,
 715                        tg110->offsets.crtc);
 716
 717        if (get_reg_field_value(
 718                value,
 719                CRTC0_CRTC_BLANK_CONTROL,
 720                CRTC_BLANK_DATA_EN) == 1 &&
 721            get_reg_field_value(
 722                value,
 723                CRTC0_CRTC_BLANK_CONTROL,
 724                CRTC_CURRENT_BLANK_STATE) == 1)
 725                        return true;
 726
 727        return false;
 728}
 729
 730static void dce120_tg_set_blank(struct timing_generator *tg,
 731                bool enable_blanking)
 732{
 733        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 734
 735        CRTC_REG_SET(
 736                CRTC0_CRTC_DOUBLE_BUFFER_CONTROL,
 737                CRTC_BLANK_DATA_DOUBLE_BUFFER_EN, 1);
 738
 739        if (enable_blanking)
 740                CRTC_REG_SET(CRTC0_CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1);
 741        else
 742                dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_BLANK_CONTROL,
 743                        tg110->offsets.crtc, 0);
 744}
 745
 746bool dce120_tg_validate_timing(struct timing_generator *tg,
 747        const struct dc_crtc_timing *timing);
 748
 749static void dce120_tg_wait_for_state(struct timing_generator *tg,
 750        enum crtc_state state)
 751{
 752        switch (state) {
 753        case CRTC_STATE_VBLANK:
 754                dce120_timing_generator_wait_for_vblank(tg);
 755                break;
 756
 757        case CRTC_STATE_VACTIVE:
 758                dce120_timing_generator_wait_for_vactive(tg);
 759                break;
 760
 761        default:
 762                break;
 763        }
 764}
 765
 766static void dce120_tg_set_colors(struct timing_generator *tg,
 767        const struct tg_color *blank_color,
 768        const struct tg_color *overscan_color)
 769{
 770        if (blank_color != NULL)
 771                dce120_tg_program_blank_color(tg, blank_color);
 772
 773        if (overscan_color != NULL)
 774                dce120_tg_set_overscan_color(tg, overscan_color);
 775}
 776
 777static void dce120_timing_generator_set_static_screen_control(
 778        struct timing_generator *tg,
 779        uint32_t event_triggers,
 780        uint32_t num_frames)
 781{
 782        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 783
 784        // By register spec, it only takes 8 bit value
 785        if (num_frames > 0xFF)
 786                num_frames = 0xFF;
 787
 788        CRTC_REG_UPDATE_2(CRTC0_CRTC_STATIC_SCREEN_CONTROL,
 789                        CRTC_STATIC_SCREEN_EVENT_MASK, event_triggers,
 790                        CRTC_STATIC_SCREEN_FRAME_COUNT, num_frames);
 791}
 792
 793static void dce120_timing_generator_set_test_pattern(
 794        struct timing_generator *tg,
 795        /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
 796         * because this is not DP-specific (which is probably somewhere in DP
 797         * encoder) */
 798        enum controller_dp_test_pattern test_pattern,
 799        enum dc_color_depth color_depth)
 800{
 801        struct dc_context *ctx = tg->ctx;
 802        uint32_t value;
 803        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 804        enum test_pattern_color_format bit_depth;
 805        enum test_pattern_dyn_range dyn_range;
 806        enum test_pattern_mode mode;
 807        /* color ramp generator mixes 16-bits color */
 808        uint32_t src_bpc = 16;
 809        /* requested bpc */
 810        uint32_t dst_bpc;
 811        uint32_t index;
 812        /* RGB values of the color bars.
 813         * Produce two RGB colors: RGB0 - white (all Fs)
 814         * and RGB1 - black (all 0s)
 815         * (three RGB components for two colors)
 816         */
 817        uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
 818                                                0x0000, 0x0000};
 819        /* dest color (converted to the specified color format) */
 820        uint16_t dst_color[6];
 821        uint32_t inc_base;
 822
 823        /* translate to bit depth */
 824        switch (color_depth) {
 825        case COLOR_DEPTH_666:
 826                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
 827        break;
 828        case COLOR_DEPTH_888:
 829                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 830        break;
 831        case COLOR_DEPTH_101010:
 832                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
 833        break;
 834        case COLOR_DEPTH_121212:
 835                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
 836        break;
 837        default:
 838                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 839        break;
 840        }
 841
 842        switch (test_pattern) {
 843        case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
 844        case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
 845        {
 846                dyn_range = (test_pattern ==
 847                                CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
 848                                TEST_PATTERN_DYN_RANGE_CEA :
 849                                TEST_PATTERN_DYN_RANGE_VESA);
 850                mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
 851
 852                CRTC_REG_UPDATE_2(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
 853                                CRTC_TEST_PATTERN_VRES, 6,
 854                                CRTC_TEST_PATTERN_HRES, 6);
 855
 856                CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
 857                                CRTC_TEST_PATTERN_EN, 1,
 858                                CRTC_TEST_PATTERN_MODE, mode,
 859                                CRTC_TEST_PATTERN_DYNAMIC_RANGE, dyn_range,
 860                                CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
 861        }
 862        break;
 863
 864        case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
 865        case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
 866        {
 867                mode = (test_pattern ==
 868                        CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
 869                        TEST_PATTERN_MODE_VERTICALBARS :
 870                        TEST_PATTERN_MODE_HORIZONTALBARS);
 871
 872                switch (bit_depth) {
 873                case TEST_PATTERN_COLOR_FORMAT_BPC_6:
 874                        dst_bpc = 6;
 875                break;
 876                case TEST_PATTERN_COLOR_FORMAT_BPC_8:
 877                        dst_bpc = 8;
 878                break;
 879                case TEST_PATTERN_COLOR_FORMAT_BPC_10:
 880                        dst_bpc = 10;
 881                break;
 882                default:
 883                        dst_bpc = 8;
 884                break;
 885                }
 886
 887                /* adjust color to the required colorFormat */
 888                for (index = 0; index < 6; index++) {
 889                        /* dst = 2^dstBpc * src / 2^srcBpc = src >>
 890                         * (srcBpc - dstBpc);
 891                         */
 892                        dst_color[index] =
 893                                src_color[index] >> (src_bpc - dst_bpc);
 894                /* CRTC_TEST_PATTERN_DATA has 16 bits,
 895                 * lowest 6 are hardwired to ZERO
 896                 * color bits should be left aligned aligned to MSB
 897                 * XXXXXXXXXX000000 for 10 bit,
 898                 * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
 899                 */
 900                        dst_color[index] <<= (16 - dst_bpc);
 901                }
 902
 903                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, 0);
 904
 905                /* We have to write the mask before data, similar to pipeline.
 906                 * For example, for 8 bpc, if we want RGB0 to be magenta,
 907                 * and RGB1 to be cyan,
 908                 * we need to make 7 writes:
 909                 * MASK   DATA
 910                 * 000001 00000000 00000000                     set mask to R0
 911                 * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
 912                 * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
 913                 * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
 914                 * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
 915                 * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
 916                 * 100000 11111111 00000000     B1 255, 0xFF00
 917                 *
 918                 * we will make a loop of 6 in which we prepare the mask,
 919                 * then write, then prepare the color for next write.
 920                 * first iteration will write mask only,
 921                 * but each next iteration color prepared in
 922                 * previous iteration will be written within new mask,
 923                 * the last component will written separately,
 924                 * mask is not changing between 6th and 7th write
 925                 * and color will be prepared by last iteration
 926                 */
 927
 928                /* write color, color values mask in CRTC_TEST_PATTERN_MASK
 929                 * is B1, G1, R1, B0, G0, R0
 930                 */
 931                value = 0;
 932                for (index = 0; index < 6; index++) {
 933                        /* prepare color mask, first write PATTERN_DATA
 934                         * will have all zeros
 935                         */
 936                        set_reg_field_value(
 937                                value,
 938                                (1 << index),
 939                                CRTC0_CRTC_TEST_PATTERN_COLOR,
 940                                CRTC_TEST_PATTERN_MASK);
 941                        /* write color component */
 942                        dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
 943                        /* prepare next color component,
 944                         * will be written in the next iteration
 945                         */
 946                        set_reg_field_value(
 947                                value,
 948                                dst_color[index],
 949                                CRTC0_CRTC_TEST_PATTERN_COLOR,
 950                                CRTC_TEST_PATTERN_DATA);
 951                }
 952                /* write last color component,
 953                 * it's been already prepared in the loop
 954                 */
 955                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
 956
 957                /* enable test pattern */
 958                CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
 959                                CRTC_TEST_PATTERN_EN, 1,
 960                                CRTC_TEST_PATTERN_MODE, mode,
 961                                CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
 962                                CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
 963        }
 964        break;
 965
 966        case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
 967        {
 968                mode = (bit_depth ==
 969                        TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
 970                        TEST_PATTERN_MODE_DUALRAMP_RGB :
 971                        TEST_PATTERN_MODE_SINGLERAMP_RGB);
 972
 973                switch (bit_depth) {
 974                case TEST_PATTERN_COLOR_FORMAT_BPC_6:
 975                        dst_bpc = 6;
 976                break;
 977                case TEST_PATTERN_COLOR_FORMAT_BPC_8:
 978                        dst_bpc = 8;
 979                break;
 980                case TEST_PATTERN_COLOR_FORMAT_BPC_10:
 981                        dst_bpc = 10;
 982                break;
 983                default:
 984                        dst_bpc = 8;
 985                break;
 986                }
 987
 988                /* increment for the first ramp for one color gradation
 989                 * 1 gradation for 6-bit color is 2^10
 990                 * gradations in 16-bit color
 991                 */
 992                inc_base = (src_bpc - dst_bpc);
 993
 994                switch (bit_depth) {
 995                case TEST_PATTERN_COLOR_FORMAT_BPC_6:
 996                {
 997                        CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
 998                                        CRTC_TEST_PATTERN_INC0, inc_base,
 999                                        CRTC_TEST_PATTERN_INC1, 0,
1000                                        CRTC_TEST_PATTERN_HRES, 6,
1001                                        CRTC_TEST_PATTERN_VRES, 6,
1002                                        CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1003                }
1004                break;
1005                case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1006                {
1007                        CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1008                                        CRTC_TEST_PATTERN_INC0, inc_base,
1009                                        CRTC_TEST_PATTERN_INC1, 0,
1010                                        CRTC_TEST_PATTERN_HRES, 8,
1011                                        CRTC_TEST_PATTERN_VRES, 6,
1012                                        CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1013                }
1014                break;
1015                case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1016                {
1017                        CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1018                                        CRTC_TEST_PATTERN_INC0, inc_base,
1019                                        CRTC_TEST_PATTERN_INC1, inc_base + 2,
1020                                        CRTC_TEST_PATTERN_HRES, 8,
1021                                        CRTC_TEST_PATTERN_VRES, 5,
1022                                        CRTC_TEST_PATTERN_RAMP0_OFFSET, 384 << 6);
1023                }
1024                break;
1025                default:
1026                break;
1027                }
1028
1029                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, 0);
1030
1031                /* enable test pattern */
1032                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, 0);
1033
1034                CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
1035                                CRTC_TEST_PATTERN_EN, 1,
1036                                CRTC_TEST_PATTERN_MODE, mode,
1037                                CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
1038                                CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1039        }
1040        break;
1041        case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1042        {
1043                value = 0;
1044                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc,  value);
1045                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
1046                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, value);
1047        }
1048        break;
1049        default:
1050        break;
1051        }
1052}
1053
1054static bool dce120_arm_vert_intr(
1055                struct timing_generator *tg,
1056                uint8_t width)
1057{
1058        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1059        uint32_t v_blank_start, v_blank_end, h_position, v_position;
1060
1061        tg->funcs->get_scanoutpos(
1062                                tg,
1063                                &v_blank_start,
1064                                &v_blank_end,
1065                                &h_position,
1066                                &v_position);
1067
1068        if (v_blank_start == 0 || v_blank_end == 0)
1069                return false;
1070
1071        CRTC_REG_SET_2(
1072                        CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION,
1073                        CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start,
1074                        CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width);
1075
1076        return true;
1077}
1078
1079
1080static bool dce120_is_tg_enabled(struct timing_generator *tg)
1081{
1082        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1083        uint32_t value, field;
1084
1085        value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CONTROL,
1086                                  tg110->offsets.crtc);
1087        field = get_reg_field_value(value, CRTC0_CRTC_CONTROL,
1088                                    CRTC_CURRENT_MASTER_EN_STATE);
1089
1090        return field == 1;
1091}
1092
1093static bool dce120_configure_crc(struct timing_generator *tg,
1094                                 const struct crc_params *params)
1095{
1096        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1097
1098        /* Cannot configure crc on a CRTC that is disabled */
1099        if (!dce120_is_tg_enabled(tg))
1100                return false;
1101
1102        /* First, disable CRC before we configure it. */
1103        dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1104                           tg110->offsets.crtc, 0);
1105
1106        if (!params->enable)
1107                return true;
1108
1109        /* Program frame boundaries */
1110        /* Window A x axis start and end. */
1111        CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_X_CONTROL,
1112                          CRTC_CRC0_WINDOWA_X_START, params->windowa_x_start,
1113                          CRTC_CRC0_WINDOWA_X_END, params->windowa_x_end);
1114
1115        /* Window A y axis start and end. */
1116        CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_Y_CONTROL,
1117                          CRTC_CRC0_WINDOWA_Y_START, params->windowa_y_start,
1118                          CRTC_CRC0_WINDOWA_Y_END, params->windowa_y_end);
1119
1120        /* Window B x axis start and end. */
1121        CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_X_CONTROL,
1122                          CRTC_CRC0_WINDOWB_X_START, params->windowb_x_start,
1123                          CRTC_CRC0_WINDOWB_X_END, params->windowb_x_end);
1124
1125        /* Window B y axis start and end. */
1126        CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_Y_CONTROL,
1127                          CRTC_CRC0_WINDOWB_Y_START, params->windowb_y_start,
1128                          CRTC_CRC0_WINDOWB_Y_END, params->windowb_y_end);
1129
1130        /* Set crc mode and selection, and enable. Only using CRC0*/
1131        CRTC_REG_UPDATE_3(CRTC0_CRTC_CRC_CNTL,
1132                          CRTC_CRC_EN, params->continuous_mode ? 1 : 0,
1133                          CRTC_CRC0_SELECT, params->selection,
1134                          CRTC_CRC_EN, 1);
1135
1136        return true;
1137}
1138
1139static bool dce120_get_crc(struct timing_generator *tg, uint32_t *r_cr,
1140                           uint32_t *g_y, uint32_t *b_cb)
1141{
1142        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1143        uint32_t value, field;
1144
1145        value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1146                                  tg110->offsets.crtc);
1147        field = get_reg_field_value(value, CRTC0_CRTC_CRC_CNTL, CRTC_CRC_EN);
1148
1149        /* Early return if CRC is not enabled for this CRTC */
1150        if (!field)
1151                return false;
1152
1153        value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_RG,
1154                                  tg110->offsets.crtc);
1155        *r_cr = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_R_CR);
1156        *g_y = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_G_Y);
1157
1158        value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_B,
1159                                  tg110->offsets.crtc);
1160        *b_cb = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_B, CRC0_B_CB);
1161
1162        return true;
1163}
1164
1165static const struct timing_generator_funcs dce120_tg_funcs = {
1166                .validate_timing = dce120_tg_validate_timing,
1167                .program_timing = dce120_tg_program_timing,
1168                .enable_crtc = dce120_timing_generator_enable_crtc,
1169                .disable_crtc = dce110_timing_generator_disable_crtc,
1170                /* used by enable_timing_synchronization. Not need for FPGA */
1171                .is_counter_moving = dce110_timing_generator_is_counter_moving,
1172                /* never be called */
1173                .get_position = dce120_timing_generator_get_crtc_position,
1174                .get_frame_count = dce120_timing_generator_get_vblank_counter,
1175                .get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos,
1176                .set_early_control = dce120_timing_generator_set_early_control,
1177                /* used by enable_timing_synchronization. Not need for FPGA */
1178                .wait_for_state = dce120_tg_wait_for_state,
1179                .set_blank = dce120_tg_set_blank,
1180                .is_blanked = dce120_tg_is_blanked,
1181                /* never be called */
1182                .set_colors = dce120_tg_set_colors,
1183                .set_overscan_blank_color = dce120_timing_generator_set_overscan_color_black,
1184                .set_blank_color = dce120_timing_generator_program_blank_color,
1185                .disable_vga = dce120_timing_generator_disable_vga,
1186                .did_triggered_reset_occur = dce120_timing_generator_did_triggered_reset_occur,
1187                .setup_global_swap_lock = dce120_timing_generator_setup_global_swap_lock,
1188                .enable_reset_trigger = dce120_timing_generator_enable_reset_trigger,
1189                .disable_reset_trigger = dce120_timing_generator_disable_reset_trigger,
1190                .tear_down_global_swap_lock = dce120_timing_generator_tear_down_global_swap_lock,
1191                .enable_advanced_request = dce120_timing_generator_enable_advanced_request,
1192                .set_drr = dce120_timing_generator_set_drr,
1193                .get_last_used_drr_vtotal = NULL,
1194                .set_static_screen_control = dce120_timing_generator_set_static_screen_control,
1195                .set_test_pattern = dce120_timing_generator_set_test_pattern,
1196                .arm_vert_intr = dce120_arm_vert_intr,
1197                .is_tg_enabled = dce120_is_tg_enabled,
1198                .configure_crc = dce120_configure_crc,
1199                .get_crc = dce120_get_crc,
1200};
1201
1202
1203void dce120_timing_generator_construct(
1204        struct dce110_timing_generator *tg110,
1205        struct dc_context *ctx,
1206        uint32_t instance,
1207        const struct dce110_timing_generator_offsets *offsets)
1208{
1209        tg110->controller_id = CONTROLLER_ID_D0 + instance;
1210        tg110->base.inst = instance;
1211
1212        tg110->offsets = *offsets;
1213
1214        tg110->base.funcs = &dce120_tg_funcs;
1215
1216        tg110->base.ctx = ctx;
1217        tg110->base.bp = ctx->dc_bios;
1218
1219        tg110->max_h_total = CRTC0_CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
1220        tg110->max_v_total = CRTC0_CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
1221
1222        /*//CRTC requires a minimum HBLANK = 32 pixels and o
1223         * Minimum HSYNC = 8 pixels*/
1224        tg110->min_h_blank = 32;
1225        /*DCE12_CRTC_Block_ARch.doc*/
1226        tg110->min_h_front_porch = 0;
1227        tg110->min_h_back_porch = 0;
1228
1229        tg110->min_h_sync_width = 4;
1230        tg110->min_v_sync_width = 1;
1231        tg110->min_v_blank = 3;
1232}
1233