linux/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c
<<
>>
Prefs
   1/*
   2 * Copyright 2016 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 "dce_mem_input.h"
  27#include "reg_helper.h"
  28#include "basics/conversion.h"
  29
  30#define CTX \
  31        dce_mi->base.ctx
  32#define REG(reg)\
  33        dce_mi->regs->reg
  34
  35#undef FN
  36#define FN(reg_name, field_name) \
  37        dce_mi->shifts->field_name, dce_mi->masks->field_name
  38
  39struct pte_setting {
  40        unsigned int bpp;
  41        unsigned int page_width;
  42        unsigned int page_height;
  43        unsigned char min_pte_before_flip_horiz_scan;
  44        unsigned char min_pte_before_flip_vert_scan;
  45        unsigned char pte_req_per_chunk;
  46        unsigned char param_6;
  47        unsigned char param_7;
  48        unsigned char param_8;
  49};
  50
  51enum mi_bits_per_pixel {
  52        mi_bpp_8 = 0,
  53        mi_bpp_16,
  54        mi_bpp_32,
  55        mi_bpp_64,
  56        mi_bpp_count,
  57};
  58
  59enum mi_tiling_format {
  60        mi_tiling_linear = 0,
  61        mi_tiling_1D,
  62        mi_tiling_2D,
  63        mi_tiling_count,
  64};
  65
  66static const struct pte_setting pte_settings[mi_tiling_count][mi_bpp_count] = {
  67        [mi_tiling_linear] = {
  68                {  8, 4096, 1, 8, 0, 1, 0, 0, 0},
  69                { 16, 2048, 1, 8, 0, 1, 0, 0, 0},
  70                { 32, 1024, 1, 8, 0, 1, 0, 0, 0},
  71                { 64,  512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */
  72        },
  73        [mi_tiling_1D] = {
  74                {  8, 512, 8, 1, 0, 1, 0, 0, 0},  /* 0 for invalid */
  75                { 16, 256, 8, 2, 0, 1, 0, 0, 0},
  76                { 32, 128, 8, 4, 0, 1, 0, 0, 0},
  77                { 64,  64, 8, 4, 0, 1, 0, 0, 0}, /* fake */
  78        },
  79        [mi_tiling_2D] = {
  80                {  8, 64, 64,  8,  8, 1, 4, 0, 0},
  81                { 16, 64, 32,  8, 16, 1, 8, 0, 0},
  82                { 32, 32, 32, 16, 16, 1, 8, 0, 0},
  83                { 64,  8, 32, 16, 16, 1, 8, 0, 0}, /* fake */
  84        },
  85};
  86
  87static enum mi_bits_per_pixel get_mi_bpp(
  88                enum surface_pixel_format format)
  89{
  90        if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616)
  91                return mi_bpp_64;
  92        else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888)
  93                return mi_bpp_32;
  94        else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555)
  95                return mi_bpp_16;
  96        else
  97                return mi_bpp_8;
  98}
  99
 100static enum mi_tiling_format get_mi_tiling(
 101                union dc_tiling_info *tiling_info)
 102{
 103        switch (tiling_info->gfx8.array_mode) {
 104        case DC_ARRAY_1D_TILED_THIN1:
 105        case DC_ARRAY_1D_TILED_THICK:
 106        case DC_ARRAY_PRT_TILED_THIN1:
 107                return mi_tiling_1D;
 108        case DC_ARRAY_2D_TILED_THIN1:
 109        case DC_ARRAY_2D_TILED_THICK:
 110        case DC_ARRAY_2D_TILED_X_THICK:
 111        case DC_ARRAY_PRT_2D_TILED_THIN1:
 112        case DC_ARRAY_PRT_2D_TILED_THICK:
 113                return mi_tiling_2D;
 114        case DC_ARRAY_LINEAR_GENERAL:
 115        case DC_ARRAY_LINEAR_ALLIGNED:
 116                return mi_tiling_linear;
 117        default:
 118                return mi_tiling_2D;
 119        }
 120}
 121
 122static bool is_vert_scan(enum dc_rotation_angle rotation)
 123{
 124        switch (rotation) {
 125        case ROTATION_ANGLE_90:
 126        case ROTATION_ANGLE_270:
 127                return true;
 128        default:
 129                return false;
 130        }
 131}
 132
 133static void dce_mi_program_pte_vm(
 134                struct mem_input *mi,
 135                enum surface_pixel_format format,
 136                union dc_tiling_info *tiling_info,
 137                enum dc_rotation_angle rotation)
 138{
 139        struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
 140        enum mi_bits_per_pixel mi_bpp = get_mi_bpp(format);
 141        enum mi_tiling_format mi_tiling = get_mi_tiling(tiling_info);
 142        const struct pte_setting *pte = &pte_settings[mi_tiling][mi_bpp];
 143
 144        unsigned int page_width = log_2(pte->page_width);
 145        unsigned int page_height = log_2(pte->page_height);
 146        unsigned int min_pte_before_flip = is_vert_scan(rotation) ?
 147                        pte->min_pte_before_flip_vert_scan :
 148                        pte->min_pte_before_flip_horiz_scan;
 149
 150        REG_UPDATE(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT,
 151                        GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, 0x7f);
 152
 153        REG_UPDATE_3(DVMM_PTE_CONTROL,
 154                        DVMM_PAGE_WIDTH, page_width,
 155                        DVMM_PAGE_HEIGHT, page_height,
 156                        DVMM_MIN_PTE_BEFORE_FLIP, min_pte_before_flip);
 157
 158        REG_UPDATE_2(DVMM_PTE_ARB_CONTROL,
 159                        DVMM_PTE_REQ_PER_CHUNK, pte->pte_req_per_chunk,
 160                        DVMM_MAX_PTE_REQ_OUTSTANDING, 0x7f);
 161}
 162
 163static void program_urgency_watermark(
 164        struct dce_mem_input *dce_mi,
 165        uint32_t wm_select,
 166        uint32_t urgency_low_wm,
 167        uint32_t urgency_high_wm)
 168{
 169        REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
 170                URGENCY_WATERMARK_MASK, wm_select);
 171
 172        REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
 173                URGENCY_LOW_WATERMARK, urgency_low_wm,
 174                URGENCY_HIGH_WATERMARK, urgency_high_wm);
 175}
 176
 177static void dce120_program_urgency_watermark(
 178        struct dce_mem_input *dce_mi,
 179        uint32_t wm_select,
 180        uint32_t urgency_low_wm,
 181        uint32_t urgency_high_wm)
 182{
 183        REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
 184                URGENCY_WATERMARK_MASK, wm_select);
 185
 186        REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
 187                URGENCY_LOW_WATERMARK, urgency_low_wm,
 188                URGENCY_HIGH_WATERMARK, urgency_high_wm);
 189
 190        REG_SET_2(DPG_PIPE_URGENT_LEVEL_CONTROL, 0,
 191                URGENT_LEVEL_LOW_WATERMARK, urgency_low_wm,
 192                URGENT_LEVEL_HIGH_WATERMARK, urgency_high_wm);
 193
 194}
 195
 196static void program_nbp_watermark(
 197        struct dce_mem_input *dce_mi,
 198        uint32_t wm_select,
 199        uint32_t nbp_wm)
 200{
 201        if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) {
 202                REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
 203                                NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select);
 204
 205                REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
 206                                NB_PSTATE_CHANGE_ENABLE, 1,
 207                                NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
 208                                NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
 209
 210                REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
 211                                NB_PSTATE_CHANGE_WATERMARK, nbp_wm);
 212        }
 213
 214        if (REG(DPG_PIPE_LOW_POWER_CONTROL)) {
 215                REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
 216                                PSTATE_CHANGE_WATERMARK_MASK, wm_select);
 217
 218                REG_UPDATE_3(DPG_PIPE_LOW_POWER_CONTROL,
 219                                PSTATE_CHANGE_ENABLE, 1,
 220                                PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
 221                                PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
 222
 223                REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL,
 224                                PSTATE_CHANGE_WATERMARK, nbp_wm);
 225        }
 226}
 227
 228static void dce120_program_stutter_watermark(
 229        struct dce_mem_input *dce_mi,
 230        uint32_t wm_select,
 231        uint32_t stutter_mark,
 232        uint32_t stutter_entry)
 233{
 234        REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
 235                STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
 236
 237        if (REG(DPG_PIPE_STUTTER_CONTROL2))
 238                REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL2,
 239                                STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
 240                                STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
 241        else
 242                REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
 243                                STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
 244                                STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
 245}
 246
 247static void program_stutter_watermark(
 248        struct dce_mem_input *dce_mi,
 249        uint32_t wm_select,
 250        uint32_t stutter_mark)
 251{
 252        REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
 253                STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
 254
 255        if (REG(DPG_PIPE_STUTTER_CONTROL2))
 256                REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2,
 257                                STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
 258        else
 259                REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
 260                                STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
 261}
 262
 263static void dce_mi_program_display_marks(
 264        struct mem_input *mi,
 265        struct dce_watermarks nbp,
 266        struct dce_watermarks stutter_exit,
 267        struct dce_watermarks stutter_enter,
 268        struct dce_watermarks urgent,
 269        uint32_t total_dest_line_time_ns)
 270{
 271        struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
 272        uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
 273
 274        program_urgency_watermark(dce_mi, 2, /* set a */
 275                        urgent.a_mark, total_dest_line_time_ns);
 276        program_urgency_watermark(dce_mi, 1, /* set d */
 277                        urgent.d_mark, total_dest_line_time_ns);
 278
 279        REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
 280                STUTTER_ENABLE, stutter_en,
 281                STUTTER_IGNORE_FBC, 1);
 282        program_nbp_watermark(dce_mi, 2, nbp.a_mark); /* set a */
 283        program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */
 284
 285        program_stutter_watermark(dce_mi, 2, stutter_exit.a_mark); /* set a */
 286        program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark); /* set d */
 287}
 288
 289static void dce112_mi_program_display_marks(struct mem_input *mi,
 290        struct dce_watermarks nbp,
 291        struct dce_watermarks stutter_exit,
 292        struct dce_watermarks stutter_entry,
 293        struct dce_watermarks urgent,
 294        uint32_t total_dest_line_time_ns)
 295{
 296        struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
 297        uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
 298
 299        program_urgency_watermark(dce_mi, 0, /* set a */
 300                        urgent.a_mark, total_dest_line_time_ns);
 301        program_urgency_watermark(dce_mi, 1, /* set b */
 302                        urgent.b_mark, total_dest_line_time_ns);
 303        program_urgency_watermark(dce_mi, 2, /* set c */
 304                        urgent.c_mark, total_dest_line_time_ns);
 305        program_urgency_watermark(dce_mi, 3, /* set d */
 306                        urgent.d_mark, total_dest_line_time_ns);
 307
 308        REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
 309                STUTTER_ENABLE, stutter_en,
 310                STUTTER_IGNORE_FBC, 1);
 311        program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */
 312        program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
 313        program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
 314        program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
 315
 316        program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark); /* set a */
 317        program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark); /* set b */
 318        program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark); /* set c */
 319        program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark); /* set d */
 320}
 321
 322static void dce120_mi_program_display_marks(struct mem_input *mi,
 323        struct dce_watermarks nbp,
 324        struct dce_watermarks stutter_exit,
 325        struct dce_watermarks stutter_entry,
 326        struct dce_watermarks urgent,
 327        uint32_t total_dest_line_time_ns)
 328{
 329        struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
 330        uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
 331
 332        dce120_program_urgency_watermark(dce_mi, 0, /* set a */
 333                        urgent.a_mark, total_dest_line_time_ns);
 334        dce120_program_urgency_watermark(dce_mi, 1, /* set b */
 335                        urgent.b_mark, total_dest_line_time_ns);
 336        dce120_program_urgency_watermark(dce_mi, 2, /* set c */
 337                        urgent.c_mark, total_dest_line_time_ns);
 338        dce120_program_urgency_watermark(dce_mi, 3, /* set d */
 339                        urgent.d_mark, total_dest_line_time_ns);
 340
 341        REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
 342                STUTTER_ENABLE, stutter_en,
 343                STUTTER_IGNORE_FBC, 1);
 344        program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */
 345        program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
 346        program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
 347        program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
 348
 349        dce120_program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark, stutter_entry.a_mark); /* set a */
 350        dce120_program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark, stutter_entry.b_mark); /* set b */
 351        dce120_program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark, stutter_entry.c_mark); /* set c */
 352        dce120_program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark, stutter_entry.d_mark); /* set d */
 353}
 354
 355static void program_tiling(
 356        struct dce_mem_input *dce_mi, const union dc_tiling_info *info)
 357{
 358        if (dce_mi->masks->GRPH_SW_MODE) { /* GFX9 */
 359                REG_UPDATE_6(GRPH_CONTROL,
 360                                GRPH_SW_MODE, info->gfx9.swizzle,
 361                                GRPH_NUM_BANKS, log_2(info->gfx9.num_banks),
 362                                GRPH_NUM_SHADER_ENGINES, log_2(info->gfx9.num_shader_engines),
 363                                GRPH_NUM_PIPES, log_2(info->gfx9.num_pipes),
 364                                GRPH_COLOR_EXPANSION_MODE, 1,
 365                                GRPH_SE_ENABLE, info->gfx9.shaderEnable);
 366                /* TODO: DCP0_GRPH_CONTROL__GRPH_SE_ENABLE where to get info
 367                GRPH_SE_ENABLE, 1,
 368                GRPH_Z, 0);
 369                 */
 370        }
 371
 372        if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */
 373                REG_UPDATE_9(GRPH_CONTROL,
 374                                GRPH_NUM_BANKS, info->gfx8.num_banks,
 375                                GRPH_BANK_WIDTH, info->gfx8.bank_width,
 376                                GRPH_BANK_HEIGHT, info->gfx8.bank_height,
 377                                GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect,
 378                                GRPH_TILE_SPLIT, info->gfx8.tile_split,
 379                                GRPH_MICRO_TILE_MODE, info->gfx8.tile_mode,
 380                                GRPH_PIPE_CONFIG, info->gfx8.pipe_config,
 381                                GRPH_ARRAY_MODE, info->gfx8.array_mode,
 382                                GRPH_COLOR_EXPANSION_MODE, 1);
 383                /* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */
 384                /*
 385                                GRPH_Z, 0);
 386                                */
 387        }
 388}
 389
 390
 391static void program_size_and_rotation(
 392        struct dce_mem_input *dce_mi,
 393        enum dc_rotation_angle rotation,
 394        const struct plane_size *plane_size)
 395{
 396        const struct rect *in_rect = &plane_size->surface_size;
 397        struct rect hw_rect = plane_size->surface_size;
 398        const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = {
 399                        [ROTATION_ANGLE_0] = 0,
 400                        [ROTATION_ANGLE_90] = 1,
 401                        [ROTATION_ANGLE_180] = 2,
 402                        [ROTATION_ANGLE_270] = 3,
 403        };
 404
 405        if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) {
 406                hw_rect.x = in_rect->y;
 407                hw_rect.y = in_rect->x;
 408
 409                hw_rect.height = in_rect->width;
 410                hw_rect.width = in_rect->height;
 411        }
 412
 413        REG_SET(GRPH_X_START, 0,
 414                        GRPH_X_START, hw_rect.x);
 415
 416        REG_SET(GRPH_Y_START, 0,
 417                        GRPH_Y_START, hw_rect.y);
 418
 419        REG_SET(GRPH_X_END, 0,
 420                        GRPH_X_END, hw_rect.width);
 421
 422        REG_SET(GRPH_Y_END, 0,
 423                        GRPH_Y_END, hw_rect.height);
 424
 425        REG_SET(GRPH_PITCH, 0,
 426                        GRPH_PITCH, plane_size->surface_pitch);
 427
 428        REG_SET(HW_ROTATION, 0,
 429                        GRPH_ROTATION_ANGLE, rotation_angles[rotation]);
 430}
 431
 432static void program_grph_pixel_format(
 433        struct dce_mem_input *dce_mi,
 434        enum surface_pixel_format format)
 435{
 436        uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */
 437        uint32_t grph_depth = 0, grph_format = 0;
 438        uint32_t sign = 0, floating = 0;
 439
 440        if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 ||
 441                        /*todo: doesn't look like we handle BGRA here,
 442                         *  should problem swap endian*/
 443                format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 ||
 444                format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS ||
 445                format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
 446                /* ABGR formats */
 447                red_xbar = 2;
 448                blue_xbar = 2;
 449        }
 450
 451        REG_SET_2(GRPH_SWAP_CNTL, 0,
 452                        GRPH_RED_CROSSBAR, red_xbar,
 453                        GRPH_BLUE_CROSSBAR, blue_xbar);
 454
 455        switch (format) {
 456        case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
 457                grph_depth = 0;
 458                grph_format = 0;
 459                break;
 460        case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
 461                grph_depth = 1;
 462                grph_format = 0;
 463                break;
 464        case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
 465                grph_depth = 1;
 466                grph_format = 1;
 467                break;
 468        case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
 469        case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
 470                grph_depth = 2;
 471                grph_format = 0;
 472                break;
 473        case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
 474        case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
 475        case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
 476                grph_depth = 2;
 477                grph_format = 1;
 478                break;
 479        case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
 480                sign = 1;
 481                floating = 1;
 482                /* fall through */
 483        case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: /* shouldn't this get float too? */
 484        case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
 485                grph_depth = 3;
 486                grph_format = 0;
 487                break;
 488        default:
 489                DC_ERR("unsupported grph pixel format");
 490                break;
 491        }
 492
 493        REG_UPDATE_2(GRPH_CONTROL,
 494                        GRPH_DEPTH, grph_depth,
 495                        GRPH_FORMAT, grph_format);
 496
 497        REG_UPDATE_4(PRESCALE_GRPH_CONTROL,
 498                        GRPH_PRESCALE_SELECT, floating,
 499                        GRPH_PRESCALE_R_SIGN, sign,
 500                        GRPH_PRESCALE_G_SIGN, sign,
 501                        GRPH_PRESCALE_B_SIGN, sign);
 502}
 503
 504static void dce_mi_program_surface_config(
 505        struct mem_input *mi,
 506        enum surface_pixel_format format,
 507        union dc_tiling_info *tiling_info,
 508        struct plane_size *plane_size,
 509        enum dc_rotation_angle rotation,
 510        struct dc_plane_dcc_param *dcc,
 511        bool horizontal_mirror)
 512{
 513        struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
 514        REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
 515
 516        program_tiling(dce_mi, tiling_info);
 517        program_size_and_rotation(dce_mi, rotation, plane_size);
 518
 519        if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
 520                format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
 521                program_grph_pixel_format(dce_mi, format);
 522}
 523
 524static uint32_t get_dmif_switch_time_us(
 525        uint32_t h_total,
 526        uint32_t v_total,
 527        uint32_t pix_clk_khz)
 528{
 529        uint32_t frame_time;
 530        uint32_t pixels_per_second;
 531        uint32_t pixels_per_frame;
 532        uint32_t refresh_rate;
 533        const uint32_t us_in_sec = 1000000;
 534        const uint32_t min_single_frame_time_us = 30000;
 535        /*return double of frame time*/
 536        const uint32_t single_frame_time_multiplier = 2;
 537
 538        if (!h_total || v_total || !pix_clk_khz)
 539                return single_frame_time_multiplier * min_single_frame_time_us;
 540
 541        /*TODO: should we use pixel format normalized pixel clock here?*/
 542        pixels_per_second = pix_clk_khz * 1000;
 543        pixels_per_frame = h_total * v_total;
 544
 545        if (!pixels_per_second || !pixels_per_frame) {
 546                /* avoid division by zero */
 547                ASSERT(pixels_per_frame);
 548                ASSERT(pixels_per_second);
 549                return single_frame_time_multiplier * min_single_frame_time_us;
 550        }
 551
 552        refresh_rate = pixels_per_second / pixels_per_frame;
 553
 554        if (!refresh_rate) {
 555                /* avoid division by zero*/
 556                ASSERT(refresh_rate);
 557                return single_frame_time_multiplier * min_single_frame_time_us;
 558        }
 559
 560        frame_time = us_in_sec / refresh_rate;
 561
 562        if (frame_time < min_single_frame_time_us)
 563                frame_time = min_single_frame_time_us;
 564
 565        frame_time *= single_frame_time_multiplier;
 566
 567        return frame_time;
 568}
 569
 570static void dce_mi_allocate_dmif(
 571        struct mem_input *mi,
 572        uint32_t h_total,
 573        uint32_t v_total,
 574        uint32_t pix_clk_khz,
 575        uint32_t total_stream_num)
 576{
 577        struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
 578        const uint32_t retry_delay = 10;
 579        uint32_t retry_count = get_dmif_switch_time_us(
 580                        h_total,
 581                        v_total,
 582                        pix_clk_khz) / retry_delay;
 583
 584        uint32_t pix_dur;
 585        uint32_t buffers_allocated;
 586        uint32_t dmif_buffer_control;
 587
 588        dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
 589                        DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
 590
 591        if (buffers_allocated == 2)
 592                return;
 593
 594        REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
 595                        DMIF_BUFFERS_ALLOCATED, 2);
 596
 597        REG_WAIT(DMIF_BUFFER_CONTROL,
 598                        DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
 599                        retry_delay, retry_count);
 600
 601        if (pix_clk_khz != 0) {
 602                pix_dur = 1000000000ULL / pix_clk_khz;
 603
 604                REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1,
 605                        PIXEL_DURATION, pix_dur);
 606        }
 607
 608        if (dce_mi->wa.single_head_rdreq_dmif_limit) {
 609                uint32_t eanble =  (total_stream_num > 1) ? 0 :
 610                                dce_mi->wa.single_head_rdreq_dmif_limit;
 611
 612                REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
 613                                ENABLE, eanble);
 614        }
 615}
 616
 617static void dce_mi_free_dmif(
 618                struct mem_input *mi,
 619                uint32_t total_stream_num)
 620{
 621        struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
 622        uint32_t buffers_allocated;
 623        uint32_t dmif_buffer_control;
 624
 625        dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
 626                        DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
 627
 628        if (buffers_allocated == 0)
 629                return;
 630
 631        REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
 632                        DMIF_BUFFERS_ALLOCATED, 0);
 633
 634        REG_WAIT(DMIF_BUFFER_CONTROL,
 635                        DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
 636                        10, 3500);
 637
 638        if (dce_mi->wa.single_head_rdreq_dmif_limit) {
 639                uint32_t eanble =  (total_stream_num > 1) ? 0 :
 640                                dce_mi->wa.single_head_rdreq_dmif_limit;
 641
 642                REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
 643                                ENABLE, eanble);
 644        }
 645}
 646
 647
 648static void program_sec_addr(
 649        struct dce_mem_input *dce_mi,
 650        PHYSICAL_ADDRESS_LOC address)
 651{
 652        /*high register MUST be programmed first*/
 653        REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0,
 654                GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,
 655                address.high_part);
 656
 657        REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS, 0,
 658                GRPH_SECONDARY_SURFACE_ADDRESS, address.low_part >> 8,
 659                GRPH_SECONDARY_DFQ_ENABLE, 0);
 660}
 661
 662static void program_pri_addr(
 663        struct dce_mem_input *dce_mi,
 664        PHYSICAL_ADDRESS_LOC address)
 665{
 666        /*high register MUST be programmed first*/
 667        REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
 668                GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,
 669                address.high_part);
 670
 671        REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS, 0,
 672                GRPH_PRIMARY_SURFACE_ADDRESS,
 673                address.low_part >> 8);
 674}
 675
 676
 677static bool dce_mi_is_flip_pending(struct mem_input *mem_input)
 678{
 679        struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
 680        uint32_t update_pending;
 681
 682        REG_GET(GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, &update_pending);
 683        if (update_pending)
 684                return true;
 685
 686        mem_input->current_address = mem_input->request_address;
 687        return false;
 688}
 689
 690static bool dce_mi_program_surface_flip_and_addr(
 691        struct mem_input *mem_input,
 692        const struct dc_plane_address *address,
 693        bool flip_immediate)
 694{
 695        struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
 696
 697        REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
 698
 699        REG_UPDATE(
 700                GRPH_FLIP_CONTROL,
 701                GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0);
 702
 703        switch (address->type) {
 704        case PLN_ADDR_TYPE_GRAPHICS:
 705                if (address->grph.addr.quad_part == 0)
 706                        break;
 707                program_pri_addr(dce_mi, address->grph.addr);
 708                break;
 709        case PLN_ADDR_TYPE_GRPH_STEREO:
 710                if (address->grph_stereo.left_addr.quad_part == 0 ||
 711                    address->grph_stereo.right_addr.quad_part == 0)
 712                        break;
 713                program_pri_addr(dce_mi, address->grph_stereo.left_addr);
 714                program_sec_addr(dce_mi, address->grph_stereo.right_addr);
 715                break;
 716        default:
 717                /* not supported */
 718                BREAK_TO_DEBUGGER();
 719                break;
 720        }
 721
 722        mem_input->request_address = *address;
 723
 724        if (flip_immediate)
 725                mem_input->current_address = *address;
 726
 727        REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
 728
 729        return true;
 730}
 731
 732static const struct mem_input_funcs dce_mi_funcs = {
 733        .mem_input_program_display_marks = dce_mi_program_display_marks,
 734        .allocate_mem_input = dce_mi_allocate_dmif,
 735        .free_mem_input = dce_mi_free_dmif,
 736        .mem_input_program_surface_flip_and_addr =
 737                        dce_mi_program_surface_flip_and_addr,
 738        .mem_input_program_pte_vm = dce_mi_program_pte_vm,
 739        .mem_input_program_surface_config =
 740                        dce_mi_program_surface_config,
 741        .mem_input_is_flip_pending = dce_mi_is_flip_pending
 742};
 743
 744static const struct mem_input_funcs dce112_mi_funcs = {
 745        .mem_input_program_display_marks = dce112_mi_program_display_marks,
 746        .allocate_mem_input = dce_mi_allocate_dmif,
 747        .free_mem_input = dce_mi_free_dmif,
 748        .mem_input_program_surface_flip_and_addr =
 749                        dce_mi_program_surface_flip_and_addr,
 750        .mem_input_program_pte_vm = dce_mi_program_pte_vm,
 751        .mem_input_program_surface_config =
 752                        dce_mi_program_surface_config,
 753        .mem_input_is_flip_pending = dce_mi_is_flip_pending
 754};
 755
 756static const struct mem_input_funcs dce120_mi_funcs = {
 757        .mem_input_program_display_marks = dce120_mi_program_display_marks,
 758        .allocate_mem_input = dce_mi_allocate_dmif,
 759        .free_mem_input = dce_mi_free_dmif,
 760        .mem_input_program_surface_flip_and_addr =
 761                        dce_mi_program_surface_flip_and_addr,
 762        .mem_input_program_pte_vm = dce_mi_program_pte_vm,
 763        .mem_input_program_surface_config =
 764                        dce_mi_program_surface_config,
 765        .mem_input_is_flip_pending = dce_mi_is_flip_pending
 766};
 767
 768void dce_mem_input_construct(
 769        struct dce_mem_input *dce_mi,
 770        struct dc_context *ctx,
 771        int inst,
 772        const struct dce_mem_input_registers *regs,
 773        const struct dce_mem_input_shift *mi_shift,
 774        const struct dce_mem_input_mask *mi_mask)
 775{
 776        dce_mi->base.ctx = ctx;
 777
 778        dce_mi->base.inst = inst;
 779        dce_mi->base.funcs = &dce_mi_funcs;
 780
 781        dce_mi->regs = regs;
 782        dce_mi->shifts = mi_shift;
 783        dce_mi->masks = mi_mask;
 784}
 785
 786void dce112_mem_input_construct(
 787        struct dce_mem_input *dce_mi,
 788        struct dc_context *ctx,
 789        int inst,
 790        const struct dce_mem_input_registers *regs,
 791        const struct dce_mem_input_shift *mi_shift,
 792        const struct dce_mem_input_mask *mi_mask)
 793{
 794        dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
 795        dce_mi->base.funcs = &dce112_mi_funcs;
 796}
 797
 798void dce120_mem_input_construct(
 799        struct dce_mem_input *dce_mi,
 800        struct dc_context *ctx,
 801        int inst,
 802        const struct dce_mem_input_registers *regs,
 803        const struct dce_mem_input_shift *mi_shift,
 804        const struct dce_mem_input_mask *mi_mask)
 805{
 806        dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
 807        dce_mi->base.funcs = &dce120_mi_funcs;
 808}
 809