root/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_mi_bpp
  2. get_mi_tiling
  3. is_vert_scan
  4. dce_mi_program_pte_vm
  5. program_urgency_watermark
  6. dce120_program_urgency_watermark
  7. program_nbp_watermark
  8. dce120_program_stutter_watermark
  9. program_stutter_watermark
  10. dce_mi_program_display_marks
  11. dce112_mi_program_display_marks
  12. dce120_mi_program_display_marks
  13. program_tiling
  14. program_size_and_rotation
  15. program_grph_pixel_format
  16. dce_mi_program_surface_config
  17. get_dmif_switch_time_us
  18. dce_mi_allocate_dmif
  19. dce_mi_free_dmif
  20. program_sec_addr
  21. program_pri_addr
  22. dce_mi_is_flip_pending
  23. dce_mi_program_surface_flip_and_addr
  24. dce_mem_input_construct
  25. dce112_mem_input_construct
  26. dce120_mem_input_construct

   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 
  39 struct 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 
  51 enum 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 
  59 enum mi_tiling_format {
  60         mi_tiling_linear = 0,
  61         mi_tiling_1D,
  62         mi_tiling_2D,
  63         mi_tiling_count,
  64 };
  65 
  66 static 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 
  87 static 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 
 100 static 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 
 122 static 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 
 133 static 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 
 163 static 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 
 177 static 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 
 196 static 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 
 228 static 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 
 247 static 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 
 263 static 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 
 289 static 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 
 322 static 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 
 355 static 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 
 391 static 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 
 432 static 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 
 504 static 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 
 524 static 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 
 570 static 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 
 617 static 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 
 648 static 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 
 662 static 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 
 677 static 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 
 690 static 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 
 732 static 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 
 744 static 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 
 756 static 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 
 768 void 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 
 786 void 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 
 798 void 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 }

/* [<][>][^][v][top][bottom][index][help] */