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_UPDATE(
 574                                CRTC0_CRTC_V_TOTAL_MIN,
 575                                CRTC_V_TOTAL_MIN, 0);
 576                CRTC_REG_UPDATE(
 577                                CRTC0_CRTC_V_TOTAL_MAX,
 578                                CRTC_V_TOTAL_MAX, 0);
 579                CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 5,
 580                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 0,
 581                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 0,
 582                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0,
 583                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0,
 584                                FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 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
 737void dce120_tg_program_timing(struct timing_generator *tg,
 738        const struct dc_crtc_timing *timing,
 739        bool use_vbios)
 740{
 741        if (use_vbios)
 742                dce110_timing_generator_program_timing_generator(tg, timing);
 743        else
 744                dce120_timing_generator_program_blanking(tg, timing);
 745}
 746
 747bool dce120_tg_is_blanked(struct timing_generator *tg)
 748{
 749        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 750        uint32_t value = dm_read_reg_soc15(
 751                        tg->ctx,
 752                        mmCRTC0_CRTC_BLANK_CONTROL,
 753                        tg110->offsets.crtc);
 754
 755        if (get_reg_field_value(
 756                value,
 757                CRTC0_CRTC_BLANK_CONTROL,
 758                CRTC_BLANK_DATA_EN) == 1 &&
 759            get_reg_field_value(
 760                value,
 761                CRTC0_CRTC_BLANK_CONTROL,
 762                CRTC_CURRENT_BLANK_STATE) == 1)
 763                        return true;
 764
 765        return false;
 766}
 767
 768void dce120_tg_set_blank(struct timing_generator *tg,
 769                bool enable_blanking)
 770{
 771        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 772
 773        CRTC_REG_SET(
 774                CRTC0_CRTC_DOUBLE_BUFFER_CONTROL,
 775                CRTC_BLANK_DATA_DOUBLE_BUFFER_EN, 0);
 776
 777        if (enable_blanking)
 778                CRTC_REG_SET(CRTC0_CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1);
 779        else
 780                dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_BLANK_CONTROL,
 781                        tg110->offsets.crtc, 0);
 782}
 783
 784bool dce120_tg_validate_timing(struct timing_generator *tg,
 785        const struct dc_crtc_timing *timing);
 786
 787void dce120_tg_wait_for_state(struct timing_generator *tg,
 788        enum crtc_state state)
 789{
 790        switch (state) {
 791        case CRTC_STATE_VBLANK:
 792                dce120_timing_generator_wait_for_vblank(tg);
 793                break;
 794
 795        case CRTC_STATE_VACTIVE:
 796                dce120_timing_generator_wait_for_vactive(tg);
 797                break;
 798
 799        default:
 800                break;
 801        }
 802}
 803
 804void dce120_tg_set_colors(struct timing_generator *tg,
 805        const struct tg_color *blank_color,
 806        const struct tg_color *overscan_color)
 807{
 808        if (blank_color != NULL)
 809                dce120_tg_program_blank_color(tg, blank_color);
 810
 811        if (overscan_color != NULL)
 812                dce120_tg_set_overscan_color(tg, overscan_color);
 813}
 814
 815static void dce120_timing_generator_set_static_screen_control(
 816        struct timing_generator *tg,
 817        uint32_t value)
 818{
 819        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 820
 821        CRTC_REG_UPDATE_2(CRTC0_CRTC_STATIC_SCREEN_CONTROL,
 822                        CRTC_STATIC_SCREEN_EVENT_MASK, value,
 823                        CRTC_STATIC_SCREEN_FRAME_COUNT, 2);
 824}
 825
 826void dce120_timing_generator_set_test_pattern(
 827        struct timing_generator *tg,
 828        /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
 829         * because this is not DP-specific (which is probably somewhere in DP
 830         * encoder) */
 831        enum controller_dp_test_pattern test_pattern,
 832        enum dc_color_depth color_depth)
 833{
 834        struct dc_context *ctx = tg->ctx;
 835        uint32_t value;
 836        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 837        enum test_pattern_color_format bit_depth;
 838        enum test_pattern_dyn_range dyn_range;
 839        enum test_pattern_mode mode;
 840        /* color ramp generator mixes 16-bits color */
 841        uint32_t src_bpc = 16;
 842        /* requested bpc */
 843        uint32_t dst_bpc;
 844        uint32_t index;
 845        /* RGB values of the color bars.
 846         * Produce two RGB colors: RGB0 - white (all Fs)
 847         * and RGB1 - black (all 0s)
 848         * (three RGB components for two colors)
 849         */
 850        uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
 851                                                0x0000, 0x0000};
 852        /* dest color (converted to the specified color format) */
 853        uint16_t dst_color[6];
 854        uint32_t inc_base;
 855
 856        /* translate to bit depth */
 857        switch (color_depth) {
 858        case COLOR_DEPTH_666:
 859                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
 860        break;
 861        case COLOR_DEPTH_888:
 862                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 863        break;
 864        case COLOR_DEPTH_101010:
 865                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
 866        break;
 867        case COLOR_DEPTH_121212:
 868                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
 869        break;
 870        default:
 871                bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 872        break;
 873        }
 874
 875        switch (test_pattern) {
 876        case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
 877        case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
 878        {
 879                dyn_range = (test_pattern ==
 880                                CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
 881                                TEST_PATTERN_DYN_RANGE_CEA :
 882                                TEST_PATTERN_DYN_RANGE_VESA);
 883                mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
 884
 885                CRTC_REG_UPDATE_2(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
 886                                CRTC_TEST_PATTERN_VRES, 6,
 887                                CRTC_TEST_PATTERN_HRES, 6);
 888
 889                CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
 890                                CRTC_TEST_PATTERN_EN, 1,
 891                                CRTC_TEST_PATTERN_MODE, mode,
 892                                CRTC_TEST_PATTERN_DYNAMIC_RANGE, dyn_range,
 893                                CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
 894        }
 895        break;
 896
 897        case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
 898        case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
 899        {
 900                mode = (test_pattern ==
 901                        CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
 902                        TEST_PATTERN_MODE_VERTICALBARS :
 903                        TEST_PATTERN_MODE_HORIZONTALBARS);
 904
 905                switch (bit_depth) {
 906                case TEST_PATTERN_COLOR_FORMAT_BPC_6:
 907                        dst_bpc = 6;
 908                break;
 909                case TEST_PATTERN_COLOR_FORMAT_BPC_8:
 910                        dst_bpc = 8;
 911                break;
 912                case TEST_PATTERN_COLOR_FORMAT_BPC_10:
 913                        dst_bpc = 10;
 914                break;
 915                default:
 916                        dst_bpc = 8;
 917                break;
 918                }
 919
 920                /* adjust color to the required colorFormat */
 921                for (index = 0; index < 6; index++) {
 922                        /* dst = 2^dstBpc * src / 2^srcBpc = src >>
 923                         * (srcBpc - dstBpc);
 924                         */
 925                        dst_color[index] =
 926                                src_color[index] >> (src_bpc - dst_bpc);
 927                /* CRTC_TEST_PATTERN_DATA has 16 bits,
 928                 * lowest 6 are hardwired to ZERO
 929                 * color bits should be left aligned aligned to MSB
 930                 * XXXXXXXXXX000000 for 10 bit,
 931                 * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
 932                 */
 933                        dst_color[index] <<= (16 - dst_bpc);
 934                }
 935
 936                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, 0);
 937
 938                /* We have to write the mask before data, similar to pipeline.
 939                 * For example, for 8 bpc, if we want RGB0 to be magenta,
 940                 * and RGB1 to be cyan,
 941                 * we need to make 7 writes:
 942                 * MASK   DATA
 943                 * 000001 00000000 00000000                     set mask to R0
 944                 * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
 945                 * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
 946                 * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
 947                 * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
 948                 * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
 949                 * 100000 11111111 00000000     B1 255, 0xFF00
 950                 *
 951                 * we will make a loop of 6 in which we prepare the mask,
 952                 * then write, then prepare the color for next write.
 953                 * first iteration will write mask only,
 954                 * but each next iteration color prepared in
 955                 * previous iteration will be written within new mask,
 956                 * the last component will written separately,
 957                 * mask is not changing between 6th and 7th write
 958                 * and color will be prepared by last iteration
 959                 */
 960
 961                /* write color, color values mask in CRTC_TEST_PATTERN_MASK
 962                 * is B1, G1, R1, B0, G0, R0
 963                 */
 964                value = 0;
 965                for (index = 0; index < 6; index++) {
 966                        /* prepare color mask, first write PATTERN_DATA
 967                         * will have all zeros
 968                         */
 969                        set_reg_field_value(
 970                                value,
 971                                (1 << index),
 972                                CRTC0_CRTC_TEST_PATTERN_COLOR,
 973                                CRTC_TEST_PATTERN_MASK);
 974                        /* write color component */
 975                        dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
 976                        /* prepare next color component,
 977                         * will be written in the next iteration
 978                         */
 979                        set_reg_field_value(
 980                                value,
 981                                dst_color[index],
 982                                CRTC0_CRTC_TEST_PATTERN_COLOR,
 983                                CRTC_TEST_PATTERN_DATA);
 984                }
 985                /* write last color component,
 986                 * it's been already prepared in the loop
 987                 */
 988                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
 989
 990                /* enable test pattern */
 991                CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
 992                                CRTC_TEST_PATTERN_EN, 1,
 993                                CRTC_TEST_PATTERN_MODE, mode,
 994                                CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
 995                                CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
 996        }
 997        break;
 998
 999        case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
1000        {
1001                mode = (bit_depth ==
1002                        TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
1003                        TEST_PATTERN_MODE_DUALRAMP_RGB :
1004                        TEST_PATTERN_MODE_SINGLERAMP_RGB);
1005
1006                switch (bit_depth) {
1007                case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1008                        dst_bpc = 6;
1009                break;
1010                case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1011                        dst_bpc = 8;
1012                break;
1013                case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1014                        dst_bpc = 10;
1015                break;
1016                default:
1017                        dst_bpc = 8;
1018                break;
1019                }
1020
1021                /* increment for the first ramp for one color gradation
1022                 * 1 gradation for 6-bit color is 2^10
1023                 * gradations in 16-bit color
1024                 */
1025                inc_base = (src_bpc - dst_bpc);
1026
1027                switch (bit_depth) {
1028                case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1029                {
1030                        CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1031                                        CRTC_TEST_PATTERN_INC0, inc_base,
1032                                        CRTC_TEST_PATTERN_INC1, 0,
1033                                        CRTC_TEST_PATTERN_HRES, 6,
1034                                        CRTC_TEST_PATTERN_VRES, 6,
1035                                        CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1036                }
1037                break;
1038                case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1039                {
1040                        CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1041                                        CRTC_TEST_PATTERN_INC0, inc_base,
1042                                        CRTC_TEST_PATTERN_INC1, 0,
1043                                        CRTC_TEST_PATTERN_HRES, 8,
1044                                        CRTC_TEST_PATTERN_VRES, 6,
1045                                        CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1046                }
1047                break;
1048                case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1049                {
1050                        CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1051                                        CRTC_TEST_PATTERN_INC0, inc_base,
1052                                        CRTC_TEST_PATTERN_INC1, inc_base + 2,
1053                                        CRTC_TEST_PATTERN_HRES, 8,
1054                                        CRTC_TEST_PATTERN_VRES, 5,
1055                                        CRTC_TEST_PATTERN_RAMP0_OFFSET, 384 << 6);
1056                }
1057                break;
1058                default:
1059                break;
1060                }
1061
1062                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, 0);
1063
1064                /* enable test pattern */
1065                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, 0);
1066
1067                CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
1068                                CRTC_TEST_PATTERN_EN, 1,
1069                                CRTC_TEST_PATTERN_MODE, mode,
1070                                CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
1071                                CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1072        }
1073        break;
1074        case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1075        {
1076                value = 0;
1077                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc,  value);
1078                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
1079                dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, value);
1080        }
1081        break;
1082        default:
1083        break;
1084        }
1085}
1086
1087static bool dce120_arm_vert_intr(
1088                struct timing_generator *tg,
1089                uint8_t width)
1090{
1091        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1092        uint32_t v_blank_start, v_blank_end, h_position, v_position;
1093
1094        tg->funcs->get_scanoutpos(
1095                                tg,
1096                                &v_blank_start,
1097                                &v_blank_end,
1098                                &h_position,
1099                                &v_position);
1100
1101        if (v_blank_start == 0 || v_blank_end == 0)
1102                return false;
1103
1104        CRTC_REG_SET_2(
1105                        CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION,
1106                        CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start,
1107                        CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width);
1108
1109        return true;
1110}
1111
1112static const struct timing_generator_funcs dce120_tg_funcs = {
1113                .validate_timing = dce120_tg_validate_timing,
1114                .program_timing = dce120_tg_program_timing,
1115                .enable_crtc = dce120_timing_generator_enable_crtc,
1116                .disable_crtc = dce110_timing_generator_disable_crtc,
1117                /* used by enable_timing_synchronization. Not need for FPGA */
1118                .is_counter_moving = dce110_timing_generator_is_counter_moving,
1119                /* never be called */
1120                .get_position = dce120_timing_generator_get_crtc_position,
1121                .get_frame_count = dce120_timing_generator_get_vblank_counter,
1122                .get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos,
1123                .set_early_control = dce120_timing_generator_set_early_control,
1124                /* used by enable_timing_synchronization. Not need for FPGA */
1125                .wait_for_state = dce120_tg_wait_for_state,
1126                .set_blank = dce120_tg_set_blank,
1127                .is_blanked = dce120_tg_is_blanked,
1128                /* never be called */
1129                .set_colors = dce120_tg_set_colors,
1130                .set_overscan_blank_color = dce120_timing_generator_set_overscan_color_black,
1131                .set_blank_color = dce120_timing_generator_program_blank_color,
1132                .disable_vga = dce120_timing_generator_disable_vga,
1133                .did_triggered_reset_occur = dce120_timing_generator_did_triggered_reset_occur,
1134                .setup_global_swap_lock = dce120_timing_generator_setup_global_swap_lock,
1135                .enable_reset_trigger = dce120_timing_generator_enable_reset_trigger,
1136                .disable_reset_trigger = dce120_timing_generator_disable_reset_trigger,
1137                .tear_down_global_swap_lock = dce120_timing_generator_tear_down_global_swap_lock,
1138                .enable_advanced_request = dce120_timing_generator_enable_advanced_request,
1139                .set_drr = dce120_timing_generator_set_drr,
1140                .set_static_screen_control = dce120_timing_generator_set_static_screen_control,
1141                .set_test_pattern = dce120_timing_generator_set_test_pattern,
1142                .arm_vert_intr = dce120_arm_vert_intr,
1143};
1144
1145
1146void dce120_timing_generator_construct(
1147        struct dce110_timing_generator *tg110,
1148        struct dc_context *ctx,
1149        uint32_t instance,
1150        const struct dce110_timing_generator_offsets *offsets)
1151{
1152        tg110->controller_id = CONTROLLER_ID_D0 + instance;
1153        tg110->base.inst = instance;
1154
1155        tg110->offsets = *offsets;
1156
1157        tg110->base.funcs = &dce120_tg_funcs;
1158
1159        tg110->base.ctx = ctx;
1160        tg110->base.bp = ctx->dc_bios;
1161
1162        tg110->max_h_total = CRTC0_CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
1163        tg110->max_v_total = CRTC0_CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
1164
1165        /*//CRTC requires a minimum HBLANK = 32 pixels and o
1166         * Minimum HSYNC = 8 pixels*/
1167        tg110->min_h_blank = 32;
1168        /*DCE12_CRTC_Block_ARch.doc*/
1169        tg110->min_h_front_porch = 0;
1170        tg110->min_h_back_porch = 0;
1171
1172        tg110->min_h_sync_width = 8;
1173        tg110->min_v_sync_width = 1;
1174        tg110->min_v_blank = 3;
1175}
1176