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 value)
 823{
 824        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 825
 826        CRTC_REG_UPDATE_2(CRTC0_CRTC_STATIC_SCREEN_CONTROL,
 827                        CRTC_STATIC_SCREEN_EVENT_MASK, value,
 828                        CRTC_STATIC_SCREEN_FRAME_COUNT, 2);
 829}
 830
 831void dce120_timing_generator_set_test_pattern(
 832        struct timing_generator *tg,
 833        /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
 834         * because this is not DP-specific (which is probably somewhere in DP
 835         * encoder) */
 836        enum controller_dp_test_pattern test_pattern,
 837        enum dc_color_depth color_depth)
 838{
 839        struct dc_context *ctx = tg->ctx;
 840        uint32_t value;
 841        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 842        enum test_pattern_color_format bit_depth;
 843        enum test_pattern_dyn_range dyn_range;
 844        enum test_pattern_mode mode;
 845        /* color ramp generator mixes 16-bits color */
 846        uint32_t src_bpc = 16;
 847        /* requested bpc */
 848        uint32_t dst_bpc;
 849        uint32_t index;
 850        /* RGB values of the color bars.
 851         * Produce two RGB colors: RGB0 - white (all Fs)
 852         * and RGB1 - black (all 0s)
 853         * (three RGB components for two colors)
 854         */
 855        uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
 856                                                0x0000, 0x0000};
 857        /* dest color (converted to the specified color format) */
 858        uint16_t dst_color[6];
 859        uint32_t inc_base;
 860
 861        /* translate to bit depth */
 862        switch (color_depth) {
 863        case COLOR_DEPTH_666:
 864                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
 865        break;
 866        case COLOR_DEPTH_888:
 867                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 868        break;
 869        case COLOR_DEPTH_101010:
 870                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
 871        break;
 872        case COLOR_DEPTH_121212:
 873                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
 874        break;
 875        default:
 876                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 877        break;
 878        }
 879
 880        switch (test_pattern) {
 881        case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
 882        case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
 883        {
 884                dyn_range = (test_pattern ==
 885                                CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
 886                                TEST_PATTERN_DYN_RANGE_CEA :
 887                                TEST_PATTERN_DYN_RANGE_VESA);
 888                mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
 889
 890                CRTC_REG_UPDATE_2(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
 891                                CRTC_TEST_PATTERN_VRES, 6,
 892                                CRTC_TEST_PATTERN_HRES, 6);
 893
 894                CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
 895                                CRTC_TEST_PATTERN_EN, 1,
 896                                CRTC_TEST_PATTERN_MODE, mode,
 897                                CRTC_TEST_PATTERN_DYNAMIC_RANGE, dyn_range,
 898                                CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
 899        }
 900        break;
 901
 902        case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
 903        case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
 904        {
 905                mode = (test_pattern ==
 906                        CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
 907                        TEST_PATTERN_MODE_VERTICALBARS :
 908                        TEST_PATTERN_MODE_HORIZONTALBARS);
 909
 910                switch (bit_depth) {
 911                case TEST_PATTERN_COLOR_FORMAT_BPC_6:
 912                        dst_bpc = 6;
 913                break;
 914                case TEST_PATTERN_COLOR_FORMAT_BPC_8:
 915                        dst_bpc = 8;
 916                break;
 917                case TEST_PATTERN_COLOR_FORMAT_BPC_10:
 918                        dst_bpc = 10;
 919                break;
 920                default:
 921                        dst_bpc = 8;
 922                break;
 923                }
 924
 925                /* adjust color to the required colorFormat */
 926                for (index = 0; index < 6; index++) {
 927                        /* dst = 2^dstBpc * src / 2^srcBpc = src >>
 928                         * (srcBpc - dstBpc);
 929                         */
 930                        dst_color[index] =
 931                                src_color[index] >> (src_bpc - dst_bpc);
 932                /* CRTC_TEST_PATTERN_DATA has 16 bits,
 933                 * lowest 6 are hardwired to ZERO
 934                 * color bits should be left aligned aligned to MSB
 935                 * XXXXXXXXXX000000 for 10 bit,
 936                 * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
 937                 */
 938                        dst_color[index] <<= (16 - dst_bpc);
 939                }
 940
 941                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, 0);
 942
 943                /* We have to write the mask before data, similar to pipeline.
 944                 * For example, for 8 bpc, if we want RGB0 to be magenta,
 945                 * and RGB1 to be cyan,
 946                 * we need to make 7 writes:
 947                 * MASK   DATA
 948                 * 000001 00000000 00000000                     set mask to R0
 949                 * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
 950                 * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
 951                 * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
 952                 * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
 953                 * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
 954                 * 100000 11111111 00000000     B1 255, 0xFF00
 955                 *
 956                 * we will make a loop of 6 in which we prepare the mask,
 957                 * then write, then prepare the color for next write.
 958                 * first iteration will write mask only,
 959                 * but each next iteration color prepared in
 960                 * previous iteration will be written within new mask,
 961                 * the last component will written separately,
 962                 * mask is not changing between 6th and 7th write
 963                 * and color will be prepared by last iteration
 964                 */
 965
 966                /* write color, color values mask in CRTC_TEST_PATTERN_MASK
 967                 * is B1, G1, R1, B0, G0, R0
 968                 */
 969                value = 0;
 970                for (index = 0; index < 6; index++) {
 971                        /* prepare color mask, first write PATTERN_DATA
 972                         * will have all zeros
 973                         */
 974                        set_reg_field_value(
 975                                value,
 976                                (1 << index),
 977                                CRTC0_CRTC_TEST_PATTERN_COLOR,
 978                                CRTC_TEST_PATTERN_MASK);
 979                        /* write color component */
 980                        dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
 981                        /* prepare next color component,
 982                         * will be written in the next iteration
 983                         */
 984                        set_reg_field_value(
 985                                value,
 986                                dst_color[index],
 987                                CRTC0_CRTC_TEST_PATTERN_COLOR,
 988                                CRTC_TEST_PATTERN_DATA);
 989                }
 990                /* write last color component,
 991                 * it's been already prepared in the loop
 992                 */
 993                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
 994
 995                /* enable test pattern */
 996                CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
 997                                CRTC_TEST_PATTERN_EN, 1,
 998                                CRTC_TEST_PATTERN_MODE, mode,
 999                                CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
1000                                CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1001        }
1002        break;
1003
1004        case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
1005        {
1006                mode = (bit_depth ==
1007                        TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
1008                        TEST_PATTERN_MODE_DUALRAMP_RGB :
1009                        TEST_PATTERN_MODE_SINGLERAMP_RGB);
1010
1011                switch (bit_depth) {
1012                case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1013                        dst_bpc = 6;
1014                break;
1015                case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1016                        dst_bpc = 8;
1017                break;
1018                case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1019                        dst_bpc = 10;
1020                break;
1021                default:
1022                        dst_bpc = 8;
1023                break;
1024                }
1025
1026                /* increment for the first ramp for one color gradation
1027                 * 1 gradation for 6-bit color is 2^10
1028                 * gradations in 16-bit color
1029                 */
1030                inc_base = (src_bpc - dst_bpc);
1031
1032                switch (bit_depth) {
1033                case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1034                {
1035                        CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1036                                        CRTC_TEST_PATTERN_INC0, inc_base,
1037                                        CRTC_TEST_PATTERN_INC1, 0,
1038                                        CRTC_TEST_PATTERN_HRES, 6,
1039                                        CRTC_TEST_PATTERN_VRES, 6,
1040                                        CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1041                }
1042                break;
1043                case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1044                {
1045                        CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1046                                        CRTC_TEST_PATTERN_INC0, inc_base,
1047                                        CRTC_TEST_PATTERN_INC1, 0,
1048                                        CRTC_TEST_PATTERN_HRES, 8,
1049                                        CRTC_TEST_PATTERN_VRES, 6,
1050                                        CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1051                }
1052                break;
1053                case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1054                {
1055                        CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1056                                        CRTC_TEST_PATTERN_INC0, inc_base,
1057                                        CRTC_TEST_PATTERN_INC1, inc_base + 2,
1058                                        CRTC_TEST_PATTERN_HRES, 8,
1059                                        CRTC_TEST_PATTERN_VRES, 5,
1060                                        CRTC_TEST_PATTERN_RAMP0_OFFSET, 384 << 6);
1061                }
1062                break;
1063                default:
1064                break;
1065                }
1066
1067                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, 0);
1068
1069                /* enable test pattern */
1070                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, 0);
1071
1072                CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
1073                                CRTC_TEST_PATTERN_EN, 1,
1074                                CRTC_TEST_PATTERN_MODE, mode,
1075                                CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
1076                                CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1077        }
1078        break;
1079        case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1080        {
1081                value = 0;
1082                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc,  value);
1083                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
1084                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, value);
1085        }
1086        break;
1087        default:
1088        break;
1089        }
1090}
1091
1092static bool dce120_arm_vert_intr(
1093                struct timing_generator *tg,
1094                uint8_t width)
1095{
1096        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1097        uint32_t v_blank_start, v_blank_end, h_position, v_position;
1098
1099        tg->funcs->get_scanoutpos(
1100                                tg,
1101                                &v_blank_start,
1102                                &v_blank_end,
1103                                &h_position,
1104                                &v_position);
1105
1106        if (v_blank_start == 0 || v_blank_end == 0)
1107                return false;
1108
1109        CRTC_REG_SET_2(
1110                        CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION,
1111                        CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start,
1112                        CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width);
1113
1114        return true;
1115}
1116
1117
1118static bool dce120_is_tg_enabled(struct timing_generator *tg)
1119{
1120        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1121        uint32_t value, field;
1122
1123        value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CONTROL,
1124                                  tg110->offsets.crtc);
1125        field = get_reg_field_value(value, CRTC0_CRTC_CONTROL,
1126                                    CRTC_CURRENT_MASTER_EN_STATE);
1127
1128        return field == 1;
1129}
1130
1131static bool dce120_configure_crc(struct timing_generator *tg,
1132                                 const struct crc_params *params)
1133{
1134        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1135
1136        /* Cannot configure crc on a CRTC that is disabled */
1137        if (!dce120_is_tg_enabled(tg))
1138                return false;
1139
1140        /* First, disable CRC before we configure it. */
1141        dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1142                           tg110->offsets.crtc, 0);
1143
1144        if (!params->enable)
1145                return true;
1146
1147        /* Program frame boundaries */
1148        /* Window A x axis start and end. */
1149        CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_X_CONTROL,
1150                          CRTC_CRC0_WINDOWA_X_START, params->windowa_x_start,
1151                          CRTC_CRC0_WINDOWA_X_END, params->windowa_x_end);
1152
1153        /* Window A y axis start and end. */
1154        CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_Y_CONTROL,
1155                          CRTC_CRC0_WINDOWA_Y_START, params->windowa_y_start,
1156                          CRTC_CRC0_WINDOWA_Y_END, params->windowa_y_end);
1157
1158        /* Window B x axis start and end. */
1159        CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_X_CONTROL,
1160                          CRTC_CRC0_WINDOWB_X_START, params->windowb_x_start,
1161                          CRTC_CRC0_WINDOWB_X_END, params->windowb_x_end);
1162
1163        /* Window B y axis start and end. */
1164        CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_Y_CONTROL,
1165                          CRTC_CRC0_WINDOWB_Y_START, params->windowb_y_start,
1166                          CRTC_CRC0_WINDOWB_Y_END, params->windowb_y_end);
1167
1168        /* Set crc mode and selection, and enable. Only using CRC0*/
1169        CRTC_REG_UPDATE_3(CRTC0_CRTC_CRC_CNTL,
1170                          CRTC_CRC_EN, params->continuous_mode ? 1 : 0,
1171                          CRTC_CRC0_SELECT, params->selection,
1172                          CRTC_CRC_EN, 1);
1173
1174        return true;
1175}
1176
1177static bool dce120_get_crc(struct timing_generator *tg, uint32_t *r_cr,
1178                           uint32_t *g_y, uint32_t *b_cb)
1179{
1180        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1181        uint32_t value, field;
1182
1183        value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1184                                  tg110->offsets.crtc);
1185        field = get_reg_field_value(value, CRTC0_CRTC_CRC_CNTL, CRTC_CRC_EN);
1186
1187        /* Early return if CRC is not enabled for this CRTC */
1188        if (!field)
1189                return false;
1190
1191        value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_RG,
1192                                  tg110->offsets.crtc);
1193        *r_cr = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_R_CR);
1194        *g_y = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_G_Y);
1195
1196        value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_B,
1197                                  tg110->offsets.crtc);
1198        *b_cb = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_B, CRC0_B_CB);
1199
1200        return true;
1201}
1202
1203static const struct timing_generator_funcs dce120_tg_funcs = {
1204                .validate_timing = dce120_tg_validate_timing,
1205                .program_timing = dce120_tg_program_timing,
1206                .enable_crtc = dce120_timing_generator_enable_crtc,
1207                .disable_crtc = dce110_timing_generator_disable_crtc,
1208                /* used by enable_timing_synchronization. Not need for FPGA */
1209                .is_counter_moving = dce110_timing_generator_is_counter_moving,
1210                /* never be called */
1211                .get_position = dce120_timing_generator_get_crtc_position,
1212                .get_frame_count = dce120_timing_generator_get_vblank_counter,
1213                .get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos,
1214                .set_early_control = dce120_timing_generator_set_early_control,
1215                /* used by enable_timing_synchronization. Not need for FPGA */
1216                .wait_for_state = dce120_tg_wait_for_state,
1217                .set_blank = dce120_tg_set_blank,
1218                .is_blanked = dce120_tg_is_blanked,
1219                /* never be called */
1220                .set_colors = dce120_tg_set_colors,
1221                .set_overscan_blank_color = dce120_timing_generator_set_overscan_color_black,
1222                .set_blank_color = dce120_timing_generator_program_blank_color,
1223                .disable_vga = dce120_timing_generator_disable_vga,
1224                .did_triggered_reset_occur = dce120_timing_generator_did_triggered_reset_occur,
1225                .setup_global_swap_lock = dce120_timing_generator_setup_global_swap_lock,
1226                .enable_reset_trigger = dce120_timing_generator_enable_reset_trigger,
1227                .disable_reset_trigger = dce120_timing_generator_disable_reset_trigger,
1228                .tear_down_global_swap_lock = dce120_timing_generator_tear_down_global_swap_lock,
1229                .enable_advanced_request = dce120_timing_generator_enable_advanced_request,
1230                .set_drr = dce120_timing_generator_set_drr,
1231                .set_static_screen_control = dce120_timing_generator_set_static_screen_control,
1232                .set_test_pattern = dce120_timing_generator_set_test_pattern,
1233                .arm_vert_intr = dce120_arm_vert_intr,
1234                .is_tg_enabled = dce120_is_tg_enabled,
1235                .configure_crc = dce120_configure_crc,
1236                .get_crc = dce120_get_crc,
1237};
1238
1239
1240void dce120_timing_generator_construct(
1241        struct dce110_timing_generator *tg110,
1242        struct dc_context *ctx,
1243        uint32_t instance,
1244        const struct dce110_timing_generator_offsets *offsets)
1245{
1246        tg110->controller_id = CONTROLLER_ID_D0 + instance;
1247        tg110->base.inst = instance;
1248
1249        tg110->offsets = *offsets;
1250
1251        tg110->base.funcs = &dce120_tg_funcs;
1252
1253        tg110->base.ctx = ctx;
1254        tg110->base.bp = ctx->dc_bios;
1255
1256        tg110->max_h_total = CRTC0_CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
1257        tg110->max_v_total = CRTC0_CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
1258
1259        /*//CRTC requires a minimum HBLANK = 32 pixels and o
1260         * Minimum HSYNC = 8 pixels*/
1261        tg110->min_h_blank = 32;
1262        /*DCE12_CRTC_Block_ARch.doc*/
1263        tg110->min_h_front_porch = 0;
1264        tg110->min_h_back_porch = 0;
1265
1266        tg110->min_h_sync_width = 8;
1267        tg110->min_v_sync_width = 1;
1268        tg110->min_v_blank = 3;
1269}
1270