Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2016 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #include "dce_mem_input.h"
0027 #include "reg_helper.h"
0028 #include "basics/conversion.h"
0029 
0030 #define CTX \
0031     dce_mi->base.ctx
0032 #define REG(reg)\
0033     dce_mi->regs->reg
0034 
0035 #undef FN
0036 #define FN(reg_name, field_name) \
0037     dce_mi->shifts->field_name, dce_mi->masks->field_name
0038 
0039 struct pte_setting {
0040     unsigned int bpp;
0041     unsigned int page_width;
0042     unsigned int page_height;
0043     unsigned char min_pte_before_flip_horiz_scan;
0044     unsigned char min_pte_before_flip_vert_scan;
0045     unsigned char pte_req_per_chunk;
0046     unsigned char param_6;
0047     unsigned char param_7;
0048     unsigned char param_8;
0049 };
0050 
0051 enum mi_bits_per_pixel {
0052     mi_bpp_8 = 0,
0053     mi_bpp_16,
0054     mi_bpp_32,
0055     mi_bpp_64,
0056     mi_bpp_count,
0057 };
0058 
0059 enum mi_tiling_format {
0060     mi_tiling_linear = 0,
0061     mi_tiling_1D,
0062     mi_tiling_2D,
0063     mi_tiling_count,
0064 };
0065 
0066 static const struct pte_setting pte_settings[mi_tiling_count][mi_bpp_count] = {
0067     [mi_tiling_linear] = {
0068         {  8, 4096, 1, 8, 0, 1, 0, 0, 0},
0069         { 16, 2048, 1, 8, 0, 1, 0, 0, 0},
0070         { 32, 1024, 1, 8, 0, 1, 0, 0, 0},
0071         { 64,  512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */
0072     },
0073     [mi_tiling_1D] = {
0074         {  8, 512, 8, 1, 0, 1, 0, 0, 0},  /* 0 for invalid */
0075         { 16, 256, 8, 2, 0, 1, 0, 0, 0},
0076         { 32, 128, 8, 4, 0, 1, 0, 0, 0},
0077         { 64,  64, 8, 4, 0, 1, 0, 0, 0}, /* fake */
0078     },
0079     [mi_tiling_2D] = {
0080         {  8, 64, 64,  8,  8, 1, 4, 0, 0},
0081         { 16, 64, 32,  8, 16, 1, 8, 0, 0},
0082         { 32, 32, 32, 16, 16, 1, 8, 0, 0},
0083         { 64,  8, 32, 16, 16, 1, 8, 0, 0}, /* fake */
0084     },
0085 };
0086 
0087 static enum mi_bits_per_pixel get_mi_bpp(
0088         enum surface_pixel_format format)
0089 {
0090     if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616)
0091         return mi_bpp_64;
0092     else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888)
0093         return mi_bpp_32;
0094     else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555)
0095         return mi_bpp_16;
0096     else
0097         return mi_bpp_8;
0098 }
0099 
0100 static enum mi_tiling_format get_mi_tiling(
0101         union dc_tiling_info *tiling_info)
0102 {
0103     switch (tiling_info->gfx8.array_mode) {
0104     case DC_ARRAY_1D_TILED_THIN1:
0105     case DC_ARRAY_1D_TILED_THICK:
0106     case DC_ARRAY_PRT_TILED_THIN1:
0107         return mi_tiling_1D;
0108     case DC_ARRAY_2D_TILED_THIN1:
0109     case DC_ARRAY_2D_TILED_THICK:
0110     case DC_ARRAY_2D_TILED_X_THICK:
0111     case DC_ARRAY_PRT_2D_TILED_THIN1:
0112     case DC_ARRAY_PRT_2D_TILED_THICK:
0113         return mi_tiling_2D;
0114     case DC_ARRAY_LINEAR_GENERAL:
0115     case DC_ARRAY_LINEAR_ALLIGNED:
0116         return mi_tiling_linear;
0117     default:
0118         return mi_tiling_2D;
0119     }
0120 }
0121 
0122 static bool is_vert_scan(enum dc_rotation_angle rotation)
0123 {
0124     switch (rotation) {
0125     case ROTATION_ANGLE_90:
0126     case ROTATION_ANGLE_270:
0127         return true;
0128     default:
0129         return false;
0130     }
0131 }
0132 
0133 static void dce_mi_program_pte_vm(
0134         struct mem_input *mi,
0135         enum surface_pixel_format format,
0136         union dc_tiling_info *tiling_info,
0137         enum dc_rotation_angle rotation)
0138 {
0139     struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
0140     enum mi_bits_per_pixel mi_bpp = get_mi_bpp(format);
0141     enum mi_tiling_format mi_tiling = get_mi_tiling(tiling_info);
0142     const struct pte_setting *pte = &pte_settings[mi_tiling][mi_bpp];
0143 
0144     unsigned int page_width = log_2(pte->page_width);
0145     unsigned int page_height = log_2(pte->page_height);
0146     unsigned int min_pte_before_flip = is_vert_scan(rotation) ?
0147             pte->min_pte_before_flip_vert_scan :
0148             pte->min_pte_before_flip_horiz_scan;
0149 
0150     REG_UPDATE(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT,
0151             GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, 0x7f);
0152 
0153     REG_UPDATE_3(DVMM_PTE_CONTROL,
0154             DVMM_PAGE_WIDTH, page_width,
0155             DVMM_PAGE_HEIGHT, page_height,
0156             DVMM_MIN_PTE_BEFORE_FLIP, min_pte_before_flip);
0157 
0158     REG_UPDATE_2(DVMM_PTE_ARB_CONTROL,
0159             DVMM_PTE_REQ_PER_CHUNK, pte->pte_req_per_chunk,
0160             DVMM_MAX_PTE_REQ_OUTSTANDING, 0x7f);
0161 }
0162 
0163 static void program_urgency_watermark(
0164     struct dce_mem_input *dce_mi,
0165     uint32_t wm_select,
0166     uint32_t urgency_low_wm,
0167     uint32_t urgency_high_wm)
0168 {
0169     REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
0170         URGENCY_WATERMARK_MASK, wm_select);
0171 
0172     REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
0173         URGENCY_LOW_WATERMARK, urgency_low_wm,
0174         URGENCY_HIGH_WATERMARK, urgency_high_wm);
0175 }
0176 
0177 #if defined(CONFIG_DRM_AMD_DC_SI)
0178 static void dce60_program_urgency_watermark(
0179     struct dce_mem_input *dce_mi,
0180     uint32_t wm_select,
0181     uint32_t urgency_low_wm,
0182     uint32_t urgency_high_wm)
0183 {
0184     REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL3,
0185         URGENCY_WATERMARK_MASK, wm_select);
0186 
0187     REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
0188         URGENCY_LOW_WATERMARK, urgency_low_wm,
0189         URGENCY_HIGH_WATERMARK, urgency_high_wm);
0190 }
0191 #endif
0192 
0193 static void dce120_program_urgency_watermark(
0194     struct dce_mem_input *dce_mi,
0195     uint32_t wm_select,
0196     uint32_t urgency_low_wm,
0197     uint32_t urgency_high_wm)
0198 {
0199     REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
0200         URGENCY_WATERMARK_MASK, wm_select);
0201 
0202     REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
0203         URGENCY_LOW_WATERMARK, urgency_low_wm,
0204         URGENCY_HIGH_WATERMARK, urgency_high_wm);
0205 
0206     REG_SET_2(DPG_PIPE_URGENT_LEVEL_CONTROL, 0,
0207         URGENT_LEVEL_LOW_WATERMARK, urgency_low_wm,
0208         URGENT_LEVEL_HIGH_WATERMARK, urgency_high_wm);
0209 
0210 }
0211 
0212 #if defined(CONFIG_DRM_AMD_DC_SI)
0213 static void dce60_program_nbp_watermark(
0214     struct dce_mem_input *dce_mi,
0215     uint32_t wm_select,
0216     uint32_t nbp_wm)
0217 {
0218     REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
0219         NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select);
0220 
0221     REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
0222         NB_PSTATE_CHANGE_ENABLE, 1,
0223         NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
0224         NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
0225 
0226     REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
0227         NB_PSTATE_CHANGE_WATERMARK, nbp_wm);
0228 }
0229 #endif
0230 
0231 static void program_nbp_watermark(
0232     struct dce_mem_input *dce_mi,
0233     uint32_t wm_select,
0234     uint32_t nbp_wm)
0235 {
0236     if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) {
0237         REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
0238                 NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select);
0239 
0240         REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
0241                 NB_PSTATE_CHANGE_ENABLE, 1,
0242                 NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
0243                 NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
0244 
0245         REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
0246                 NB_PSTATE_CHANGE_WATERMARK, nbp_wm);
0247     }
0248 
0249     if (REG(DPG_PIPE_LOW_POWER_CONTROL)) {
0250         REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
0251                 PSTATE_CHANGE_WATERMARK_MASK, wm_select);
0252 
0253         REG_UPDATE_3(DPG_PIPE_LOW_POWER_CONTROL,
0254                 PSTATE_CHANGE_ENABLE, 1,
0255                 PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
0256                 PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
0257 
0258         REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL,
0259                 PSTATE_CHANGE_WATERMARK, nbp_wm);
0260     }
0261 }
0262 
0263 #if defined(CONFIG_DRM_AMD_DC_SI)
0264 static void dce60_program_stutter_watermark(
0265     struct dce_mem_input *dce_mi,
0266     uint32_t wm_select,
0267     uint32_t stutter_mark)
0268 {
0269     REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
0270         STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
0271 
0272     REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
0273         STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
0274 }
0275 #endif
0276 
0277 static void dce120_program_stutter_watermark(
0278     struct dce_mem_input *dce_mi,
0279     uint32_t wm_select,
0280     uint32_t stutter_mark,
0281     uint32_t stutter_entry)
0282 {
0283     REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
0284         STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
0285 
0286     if (REG(DPG_PIPE_STUTTER_CONTROL2))
0287         REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL2,
0288                 STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
0289                 STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
0290     else
0291         REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
0292                 STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
0293                 STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
0294 }
0295 
0296 static void program_stutter_watermark(
0297     struct dce_mem_input *dce_mi,
0298     uint32_t wm_select,
0299     uint32_t stutter_mark)
0300 {
0301     REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
0302         STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
0303 
0304     if (REG(DPG_PIPE_STUTTER_CONTROL2))
0305         REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2,
0306                 STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
0307     else
0308         REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
0309                 STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
0310 }
0311 
0312 static void dce_mi_program_display_marks(
0313     struct mem_input *mi,
0314     struct dce_watermarks nbp,
0315     struct dce_watermarks stutter_exit,
0316     struct dce_watermarks stutter_enter,
0317     struct dce_watermarks urgent,
0318     uint32_t total_dest_line_time_ns)
0319 {
0320     struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
0321     uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
0322 
0323     program_urgency_watermark(dce_mi, 2, /* set a */
0324             urgent.a_mark, total_dest_line_time_ns);
0325     program_urgency_watermark(dce_mi, 1, /* set d */
0326             urgent.d_mark, total_dest_line_time_ns);
0327 
0328     REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
0329         STUTTER_ENABLE, stutter_en,
0330         STUTTER_IGNORE_FBC, 1);
0331     program_nbp_watermark(dce_mi, 2, nbp.a_mark); /* set a */
0332     program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */
0333 
0334     program_stutter_watermark(dce_mi, 2, stutter_exit.a_mark); /* set a */
0335     program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark); /* set d */
0336 }
0337 
0338 #if defined(CONFIG_DRM_AMD_DC_SI)
0339 static void dce60_mi_program_display_marks(
0340     struct mem_input *mi,
0341     struct dce_watermarks nbp,
0342     struct dce_watermarks stutter_exit,
0343     struct dce_watermarks stutter_enter,
0344     struct dce_watermarks urgent,
0345     uint32_t total_dest_line_time_ns)
0346 {
0347     struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
0348     uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
0349 
0350     dce60_program_urgency_watermark(dce_mi, 2, /* set a */
0351             urgent.a_mark, total_dest_line_time_ns);
0352     dce60_program_urgency_watermark(dce_mi, 1, /* set d */
0353             urgent.d_mark, total_dest_line_time_ns);
0354 
0355     REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
0356         STUTTER_ENABLE, stutter_en,
0357         STUTTER_IGNORE_FBC, 1);
0358     dce60_program_nbp_watermark(dce_mi, 2, nbp.a_mark); /* set a */
0359     dce60_program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */
0360 
0361     dce60_program_stutter_watermark(dce_mi, 2, stutter_exit.a_mark); /* set a */
0362     dce60_program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark); /* set d */
0363 }
0364 #endif
0365 
0366 static void dce112_mi_program_display_marks(struct mem_input *mi,
0367     struct dce_watermarks nbp,
0368     struct dce_watermarks stutter_exit,
0369     struct dce_watermarks stutter_entry,
0370     struct dce_watermarks urgent,
0371     uint32_t total_dest_line_time_ns)
0372 {
0373     struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
0374     uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
0375 
0376     program_urgency_watermark(dce_mi, 0, /* set a */
0377             urgent.a_mark, total_dest_line_time_ns);
0378     program_urgency_watermark(dce_mi, 1, /* set b */
0379             urgent.b_mark, total_dest_line_time_ns);
0380     program_urgency_watermark(dce_mi, 2, /* set c */
0381             urgent.c_mark, total_dest_line_time_ns);
0382     program_urgency_watermark(dce_mi, 3, /* set d */
0383             urgent.d_mark, total_dest_line_time_ns);
0384 
0385     REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
0386         STUTTER_ENABLE, stutter_en,
0387         STUTTER_IGNORE_FBC, 1);
0388     program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */
0389     program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
0390     program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
0391     program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
0392 
0393     program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark); /* set a */
0394     program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark); /* set b */
0395     program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark); /* set c */
0396     program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark); /* set d */
0397 }
0398 
0399 static void dce120_mi_program_display_marks(struct mem_input *mi,
0400     struct dce_watermarks nbp,
0401     struct dce_watermarks stutter_exit,
0402     struct dce_watermarks stutter_entry,
0403     struct dce_watermarks urgent,
0404     uint32_t total_dest_line_time_ns)
0405 {
0406     struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
0407     uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
0408 
0409     dce120_program_urgency_watermark(dce_mi, 0, /* set a */
0410             urgent.a_mark, total_dest_line_time_ns);
0411     dce120_program_urgency_watermark(dce_mi, 1, /* set b */
0412             urgent.b_mark, total_dest_line_time_ns);
0413     dce120_program_urgency_watermark(dce_mi, 2, /* set c */
0414             urgent.c_mark, total_dest_line_time_ns);
0415     dce120_program_urgency_watermark(dce_mi, 3, /* set d */
0416             urgent.d_mark, total_dest_line_time_ns);
0417 
0418     REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
0419         STUTTER_ENABLE, stutter_en,
0420         STUTTER_IGNORE_FBC, 1);
0421     program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */
0422     program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
0423     program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
0424     program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
0425 
0426     dce120_program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark, stutter_entry.a_mark); /* set a */
0427     dce120_program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark, stutter_entry.b_mark); /* set b */
0428     dce120_program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark, stutter_entry.c_mark); /* set c */
0429     dce120_program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark, stutter_entry.d_mark); /* set d */
0430 }
0431 
0432 static void program_tiling(
0433     struct dce_mem_input *dce_mi, const union dc_tiling_info *info)
0434 {
0435     if (dce_mi->masks->GRPH_SW_MODE) { /* GFX9 */
0436         REG_UPDATE_6(GRPH_CONTROL,
0437                 GRPH_SW_MODE, info->gfx9.swizzle,
0438                 GRPH_NUM_BANKS, log_2(info->gfx9.num_banks),
0439                 GRPH_NUM_SHADER_ENGINES, log_2(info->gfx9.num_shader_engines),
0440                 GRPH_NUM_PIPES, log_2(info->gfx9.num_pipes),
0441                 GRPH_COLOR_EXPANSION_MODE, 1,
0442                 GRPH_SE_ENABLE, info->gfx9.shaderEnable);
0443         /* TODO: DCP0_GRPH_CONTROL__GRPH_SE_ENABLE where to get info
0444         GRPH_SE_ENABLE, 1,
0445         GRPH_Z, 0);
0446          */
0447     }
0448 
0449     if (dce_mi->masks->GRPH_MICRO_TILE_MODE) { /* GFX8 */
0450         REG_UPDATE_9(GRPH_CONTROL,
0451                 GRPH_NUM_BANKS, info->gfx8.num_banks,
0452                 GRPH_BANK_WIDTH, info->gfx8.bank_width,
0453                 GRPH_BANK_HEIGHT, info->gfx8.bank_height,
0454                 GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect,
0455                 GRPH_TILE_SPLIT, info->gfx8.tile_split,
0456                 GRPH_MICRO_TILE_MODE, info->gfx8.tile_mode,
0457                 GRPH_PIPE_CONFIG, info->gfx8.pipe_config,
0458                 GRPH_ARRAY_MODE, info->gfx8.array_mode,
0459                 GRPH_COLOR_EXPANSION_MODE, 1);
0460         /* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */
0461         /*
0462                 GRPH_Z, 0);
0463                 */
0464     }
0465 
0466     if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX6 but reuses gfx8 struct */
0467         REG_UPDATE_8(GRPH_CONTROL,
0468                 GRPH_NUM_BANKS, info->gfx8.num_banks,
0469                 GRPH_BANK_WIDTH, info->gfx8.bank_width,
0470                 GRPH_BANK_HEIGHT, info->gfx8.bank_height,
0471                 GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect,
0472                 GRPH_TILE_SPLIT, info->gfx8.tile_split,
0473                 /* DCE6 has no GRPH_MICRO_TILE_MODE mask */
0474                 GRPH_PIPE_CONFIG, info->gfx8.pipe_config,
0475                 GRPH_ARRAY_MODE, info->gfx8.array_mode,
0476                 GRPH_COLOR_EXPANSION_MODE, 1);
0477         /* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */
0478         /*
0479                 GRPH_Z, 0);
0480                 */
0481     }
0482 }
0483 
0484 
0485 static void program_size_and_rotation(
0486     struct dce_mem_input *dce_mi,
0487     enum dc_rotation_angle rotation,
0488     const struct plane_size *plane_size)
0489 {
0490     const struct rect *in_rect = &plane_size->surface_size;
0491     struct rect hw_rect = plane_size->surface_size;
0492     const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = {
0493             [ROTATION_ANGLE_0] = 0,
0494             [ROTATION_ANGLE_90] = 1,
0495             [ROTATION_ANGLE_180] = 2,
0496             [ROTATION_ANGLE_270] = 3,
0497     };
0498 
0499     if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) {
0500         hw_rect.x = in_rect->y;
0501         hw_rect.y = in_rect->x;
0502 
0503         hw_rect.height = in_rect->width;
0504         hw_rect.width = in_rect->height;
0505     }
0506 
0507     REG_SET(GRPH_X_START, 0,
0508             GRPH_X_START, hw_rect.x);
0509 
0510     REG_SET(GRPH_Y_START, 0,
0511             GRPH_Y_START, hw_rect.y);
0512 
0513     REG_SET(GRPH_X_END, 0,
0514             GRPH_X_END, hw_rect.width);
0515 
0516     REG_SET(GRPH_Y_END, 0,
0517             GRPH_Y_END, hw_rect.height);
0518 
0519     REG_SET(GRPH_PITCH, 0,
0520             GRPH_PITCH, plane_size->surface_pitch);
0521 
0522     REG_SET(HW_ROTATION, 0,
0523             GRPH_ROTATION_ANGLE, rotation_angles[rotation]);
0524 }
0525 
0526 #if defined(CONFIG_DRM_AMD_DC_SI)
0527 static void dce60_program_size(
0528     struct dce_mem_input *dce_mi,
0529     enum dc_rotation_angle rotation, /* not used in DCE6 */
0530     const struct plane_size *plane_size)
0531 {
0532     struct rect hw_rect = plane_size->surface_size;
0533     /* DCE6 has no HW rotation, skip rotation_angles declaration */
0534 
0535     /* DCE6 has no HW rotation, skip ROTATION_ANGLE_* processing */
0536 
0537     REG_SET(GRPH_X_START, 0,
0538             GRPH_X_START, hw_rect.x);
0539 
0540     REG_SET(GRPH_Y_START, 0,
0541             GRPH_Y_START, hw_rect.y);
0542 
0543     REG_SET(GRPH_X_END, 0,
0544             GRPH_X_END, hw_rect.width);
0545 
0546     REG_SET(GRPH_Y_END, 0,
0547             GRPH_Y_END, hw_rect.height);
0548 
0549     REG_SET(GRPH_PITCH, 0,
0550             GRPH_PITCH, plane_size->surface_pitch);
0551 
0552     /* DCE6 has no HW_ROTATION register, skip setting rotation_angles */
0553 }
0554 #endif
0555 
0556 static void program_grph_pixel_format(
0557     struct dce_mem_input *dce_mi,
0558     enum surface_pixel_format format)
0559 {
0560     uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */
0561     uint32_t grph_depth = 0, grph_format = 0;
0562     uint32_t sign = 0, floating = 0;
0563 
0564     if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 ||
0565             /*todo: doesn't look like we handle BGRA here,
0566              *  should problem swap endian*/
0567         format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 ||
0568         format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS ||
0569         format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 ||
0570         format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
0571         /* ABGR formats */
0572         red_xbar = 2;
0573         blue_xbar = 2;
0574     }
0575 
0576     REG_SET_2(GRPH_SWAP_CNTL, 0,
0577             GRPH_RED_CROSSBAR, red_xbar,
0578             GRPH_BLUE_CROSSBAR, blue_xbar);
0579 
0580     switch (format) {
0581     case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
0582         grph_depth = 0;
0583         grph_format = 0;
0584         break;
0585     case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
0586         grph_depth = 1;
0587         grph_format = 0;
0588         break;
0589     case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
0590         grph_depth = 1;
0591         grph_format = 1;
0592         break;
0593     case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
0594     case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
0595         grph_depth = 2;
0596         grph_format = 0;
0597         break;
0598     case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
0599     case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
0600     case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
0601         grph_depth = 2;
0602         grph_format = 1;
0603         break;
0604     case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
0605         sign = 1;
0606         floating = 1;
0607         fallthrough;
0608     case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: /* shouldn't this get float too? */
0609     case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
0610     case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
0611         grph_depth = 3;
0612         grph_format = 0;
0613         break;
0614     default:
0615         DC_ERR("unsupported grph pixel format");
0616         break;
0617     }
0618 
0619     REG_UPDATE_2(GRPH_CONTROL,
0620             GRPH_DEPTH, grph_depth,
0621             GRPH_FORMAT, grph_format);
0622 
0623     REG_UPDATE_4(PRESCALE_GRPH_CONTROL,
0624             GRPH_PRESCALE_SELECT, floating,
0625             GRPH_PRESCALE_R_SIGN, sign,
0626             GRPH_PRESCALE_G_SIGN, sign,
0627             GRPH_PRESCALE_B_SIGN, sign);
0628 }
0629 
0630 static void dce_mi_program_surface_config(
0631     struct mem_input *mi,
0632     enum surface_pixel_format format,
0633     union dc_tiling_info *tiling_info,
0634     struct plane_size *plane_size,
0635     enum dc_rotation_angle rotation,
0636     struct dc_plane_dcc_param *dcc,
0637     bool horizontal_mirror)
0638 {
0639     struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
0640     REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
0641 
0642     program_tiling(dce_mi, tiling_info);
0643     program_size_and_rotation(dce_mi, rotation, plane_size);
0644 
0645     if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
0646         format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
0647         program_grph_pixel_format(dce_mi, format);
0648 }
0649 
0650 #if defined(CONFIG_DRM_AMD_DC_SI)
0651 static void dce60_mi_program_surface_config(
0652     struct mem_input *mi,
0653     enum surface_pixel_format format,
0654     union dc_tiling_info *tiling_info,
0655     struct plane_size *plane_size,
0656     enum dc_rotation_angle rotation, /* not used in DCE6 */
0657     struct dc_plane_dcc_param *dcc,
0658     bool horizontal_mirror)
0659 {
0660     struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
0661     REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
0662 
0663     program_tiling(dce_mi, tiling_info);
0664     dce60_program_size(dce_mi, rotation, plane_size);
0665 
0666     if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
0667         format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
0668         program_grph_pixel_format(dce_mi, format);
0669 }
0670 #endif
0671 
0672 static uint32_t get_dmif_switch_time_us(
0673     uint32_t h_total,
0674     uint32_t v_total,
0675     uint32_t pix_clk_khz)
0676 {
0677     uint32_t frame_time;
0678     uint32_t pixels_per_second;
0679     uint32_t pixels_per_frame;
0680     uint32_t refresh_rate;
0681     const uint32_t us_in_sec = 1000000;
0682     const uint32_t min_single_frame_time_us = 30000;
0683     /*return double of frame time*/
0684     const uint32_t single_frame_time_multiplier = 2;
0685 
0686     if (!h_total || v_total || !pix_clk_khz)
0687         return single_frame_time_multiplier * min_single_frame_time_us;
0688 
0689     /*TODO: should we use pixel format normalized pixel clock here?*/
0690     pixels_per_second = pix_clk_khz * 1000;
0691     pixels_per_frame = h_total * v_total;
0692 
0693     if (!pixels_per_second || !pixels_per_frame) {
0694         /* avoid division by zero */
0695         ASSERT(pixels_per_frame);
0696         ASSERT(pixels_per_second);
0697         return single_frame_time_multiplier * min_single_frame_time_us;
0698     }
0699 
0700     refresh_rate = pixels_per_second / pixels_per_frame;
0701 
0702     if (!refresh_rate) {
0703         /* avoid division by zero*/
0704         ASSERT(refresh_rate);
0705         return single_frame_time_multiplier * min_single_frame_time_us;
0706     }
0707 
0708     frame_time = us_in_sec / refresh_rate;
0709 
0710     if (frame_time < min_single_frame_time_us)
0711         frame_time = min_single_frame_time_us;
0712 
0713     frame_time *= single_frame_time_multiplier;
0714 
0715     return frame_time;
0716 }
0717 
0718 static void dce_mi_allocate_dmif(
0719     struct mem_input *mi,
0720     uint32_t h_total,
0721     uint32_t v_total,
0722     uint32_t pix_clk_khz,
0723     uint32_t total_stream_num)
0724 {
0725     struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
0726     const uint32_t retry_delay = 10;
0727     uint32_t retry_count = get_dmif_switch_time_us(
0728             h_total,
0729             v_total,
0730             pix_clk_khz) / retry_delay;
0731 
0732     uint32_t pix_dur;
0733     uint32_t buffers_allocated;
0734     uint32_t dmif_buffer_control;
0735 
0736     dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
0737             DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
0738 
0739     if (buffers_allocated == 2)
0740         return;
0741 
0742     REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
0743             DMIF_BUFFERS_ALLOCATED, 2);
0744 
0745     REG_WAIT(DMIF_BUFFER_CONTROL,
0746             DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
0747             retry_delay, retry_count);
0748 
0749     if (pix_clk_khz != 0) {
0750         pix_dur = 1000000000ULL / pix_clk_khz;
0751 
0752         REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1,
0753             PIXEL_DURATION, pix_dur);
0754     }
0755 
0756     if (dce_mi->wa.single_head_rdreq_dmif_limit) {
0757         uint32_t enable =  (total_stream_num > 1) ? 0 :
0758                 dce_mi->wa.single_head_rdreq_dmif_limit;
0759 
0760         REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
0761                 ENABLE, enable);
0762     }
0763 }
0764 
0765 static void dce_mi_free_dmif(
0766         struct mem_input *mi,
0767         uint32_t total_stream_num)
0768 {
0769     struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
0770     uint32_t buffers_allocated;
0771     uint32_t dmif_buffer_control;
0772 
0773     dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
0774             DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
0775 
0776     if (buffers_allocated == 0)
0777         return;
0778 
0779     REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
0780             DMIF_BUFFERS_ALLOCATED, 0);
0781 
0782     REG_WAIT(DMIF_BUFFER_CONTROL,
0783             DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
0784             10, 3500);
0785 
0786     if (dce_mi->wa.single_head_rdreq_dmif_limit) {
0787         uint32_t enable =  (total_stream_num > 1) ? 0 :
0788                 dce_mi->wa.single_head_rdreq_dmif_limit;
0789 
0790         REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
0791                 ENABLE, enable);
0792     }
0793 }
0794 
0795 
0796 static void program_sec_addr(
0797     struct dce_mem_input *dce_mi,
0798     PHYSICAL_ADDRESS_LOC address)
0799 {
0800     /*high register MUST be programmed first*/
0801     REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0,
0802         GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,
0803         address.high_part);
0804 
0805     REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS, 0,
0806         GRPH_SECONDARY_SURFACE_ADDRESS, address.low_part >> 8,
0807         GRPH_SECONDARY_DFQ_ENABLE, 0);
0808 }
0809 
0810 static void program_pri_addr(
0811     struct dce_mem_input *dce_mi,
0812     PHYSICAL_ADDRESS_LOC address)
0813 {
0814     /*high register MUST be programmed first*/
0815     REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
0816         GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,
0817         address.high_part);
0818 
0819     REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS, 0,
0820         GRPH_PRIMARY_SURFACE_ADDRESS,
0821         address.low_part >> 8);
0822 }
0823 
0824 
0825 static bool dce_mi_is_flip_pending(struct mem_input *mem_input)
0826 {
0827     struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
0828     uint32_t update_pending;
0829 
0830     REG_GET(GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, &update_pending);
0831     if (update_pending)
0832         return true;
0833 
0834     mem_input->current_address = mem_input->request_address;
0835     return false;
0836 }
0837 
0838 static bool dce_mi_program_surface_flip_and_addr(
0839     struct mem_input *mem_input,
0840     const struct dc_plane_address *address,
0841     bool flip_immediate)
0842 {
0843     struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
0844 
0845     REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
0846 
0847     REG_UPDATE(
0848         GRPH_FLIP_CONTROL,
0849         GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0);
0850 
0851     switch (address->type) {
0852     case PLN_ADDR_TYPE_GRAPHICS:
0853         if (address->grph.addr.quad_part == 0)
0854             break;
0855         program_pri_addr(dce_mi, address->grph.addr);
0856         break;
0857     case PLN_ADDR_TYPE_GRPH_STEREO:
0858         if (address->grph_stereo.left_addr.quad_part == 0 ||
0859             address->grph_stereo.right_addr.quad_part == 0)
0860             break;
0861         program_pri_addr(dce_mi, address->grph_stereo.left_addr);
0862         program_sec_addr(dce_mi, address->grph_stereo.right_addr);
0863         break;
0864     default:
0865         /* not supported */
0866         BREAK_TO_DEBUGGER();
0867         break;
0868     }
0869 
0870     mem_input->request_address = *address;
0871 
0872     if (flip_immediate)
0873         mem_input->current_address = *address;
0874 
0875     REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
0876 
0877     return true;
0878 }
0879 
0880 static const struct mem_input_funcs dce_mi_funcs = {
0881     .mem_input_program_display_marks = dce_mi_program_display_marks,
0882     .allocate_mem_input = dce_mi_allocate_dmif,
0883     .free_mem_input = dce_mi_free_dmif,
0884     .mem_input_program_surface_flip_and_addr =
0885             dce_mi_program_surface_flip_and_addr,
0886     .mem_input_program_pte_vm = dce_mi_program_pte_vm,
0887     .mem_input_program_surface_config =
0888             dce_mi_program_surface_config,
0889     .mem_input_is_flip_pending = dce_mi_is_flip_pending
0890 };
0891 
0892 #if defined(CONFIG_DRM_AMD_DC_SI)
0893 static const struct mem_input_funcs dce60_mi_funcs = {
0894     .mem_input_program_display_marks = dce60_mi_program_display_marks,
0895     .allocate_mem_input = dce_mi_allocate_dmif,
0896     .free_mem_input = dce_mi_free_dmif,
0897     .mem_input_program_surface_flip_and_addr =
0898             dce_mi_program_surface_flip_and_addr,
0899     .mem_input_program_pte_vm = dce_mi_program_pte_vm,
0900     .mem_input_program_surface_config =
0901             dce60_mi_program_surface_config,
0902     .mem_input_is_flip_pending = dce_mi_is_flip_pending
0903 };
0904 #endif
0905 
0906 static const struct mem_input_funcs dce112_mi_funcs = {
0907     .mem_input_program_display_marks = dce112_mi_program_display_marks,
0908     .allocate_mem_input = dce_mi_allocate_dmif,
0909     .free_mem_input = dce_mi_free_dmif,
0910     .mem_input_program_surface_flip_and_addr =
0911             dce_mi_program_surface_flip_and_addr,
0912     .mem_input_program_pte_vm = dce_mi_program_pte_vm,
0913     .mem_input_program_surface_config =
0914             dce_mi_program_surface_config,
0915     .mem_input_is_flip_pending = dce_mi_is_flip_pending
0916 };
0917 
0918 static const struct mem_input_funcs dce120_mi_funcs = {
0919     .mem_input_program_display_marks = dce120_mi_program_display_marks,
0920     .allocate_mem_input = dce_mi_allocate_dmif,
0921     .free_mem_input = dce_mi_free_dmif,
0922     .mem_input_program_surface_flip_and_addr =
0923             dce_mi_program_surface_flip_and_addr,
0924     .mem_input_program_pte_vm = dce_mi_program_pte_vm,
0925     .mem_input_program_surface_config =
0926             dce_mi_program_surface_config,
0927     .mem_input_is_flip_pending = dce_mi_is_flip_pending
0928 };
0929 
0930 void dce_mem_input_construct(
0931     struct dce_mem_input *dce_mi,
0932     struct dc_context *ctx,
0933     int inst,
0934     const struct dce_mem_input_registers *regs,
0935     const struct dce_mem_input_shift *mi_shift,
0936     const struct dce_mem_input_mask *mi_mask)
0937 {
0938     dce_mi->base.ctx = ctx;
0939 
0940     dce_mi->base.inst = inst;
0941     dce_mi->base.funcs = &dce_mi_funcs;
0942 
0943     dce_mi->regs = regs;
0944     dce_mi->shifts = mi_shift;
0945     dce_mi->masks = mi_mask;
0946 }
0947 
0948 #if defined(CONFIG_DRM_AMD_DC_SI)
0949 void dce60_mem_input_construct(
0950     struct dce_mem_input *dce_mi,
0951     struct dc_context *ctx,
0952     int inst,
0953     const struct dce_mem_input_registers *regs,
0954     const struct dce_mem_input_shift *mi_shift,
0955     const struct dce_mem_input_mask *mi_mask)
0956 {
0957     dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
0958     dce_mi->base.funcs = &dce60_mi_funcs;
0959 }
0960 #endif
0961 
0962 void dce112_mem_input_construct(
0963     struct dce_mem_input *dce_mi,
0964     struct dc_context *ctx,
0965     int inst,
0966     const struct dce_mem_input_registers *regs,
0967     const struct dce_mem_input_shift *mi_shift,
0968     const struct dce_mem_input_mask *mi_mask)
0969 {
0970     dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
0971     dce_mi->base.funcs = &dce112_mi_funcs;
0972 }
0973 
0974 void dce120_mem_input_construct(
0975     struct dce_mem_input *dce_mi,
0976     struct dc_context *ctx,
0977     int inst,
0978     const struct dce_mem_input_registers *regs,
0979     const struct dce_mem_input_shift *mi_shift,
0980     const struct dce_mem_input_mask *mi_mask)
0981 {
0982     dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
0983     dce_mi->base.funcs = &dce120_mi_funcs;
0984 }