1 /* 2 * Copyright 2018 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 "reg_helper.h" 27 #include "core_types.h" 28 #include "dcn20/dcn20_dccg.h" 29 #include "dcn21_dccg.h" 30 31 #define TO_DCN_DCCG(dccg)\ 32 container_of(dccg, struct dcn_dccg, base) 33 34 #define REG(reg) \ 35 (dccg_dcn->regs->reg) 36 37 #undef FN 38 #define FN(reg_name, field_name) \ 39 dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name 40 41 #define CTX \ 42 dccg_dcn->base.ctx 43 #define DC_LOGGER \ 44 dccg->ctx->logger 45 46 static void dccg21_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk) 47 { 48 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 49 50 if (dccg->ref_dppclk) { 51 int ref_dppclk = dccg->ref_dppclk; 52 int modulo = ref_dppclk / 10000; 53 int phase; 54 55 if (req_dppclk) { 56 /* 57 * program DPP DTO phase and modulo as below 58 * phase = ceiling(dpp_pipe_clk_mhz / 10) 59 * module = trunc(dpp_global_clk_mhz / 10) 60 * 61 * storing frequencies in registers allow dmcub fw 62 * to run time lower clocks when possible for power saving 63 * 64 * ceiling phase and truncate modulo guarentees the divided 65 * down per pipe dpp clock has high enough frequency 66 */ 67 phase = (req_dppclk + 9999) / 10000; 68 69 if (phase > modulo) { 70 /* phase > modulo result in screen corruption 71 * ie phase = 30, mod = 29 for 4k@60 HDMI 72 * in these case we don't want pipe clock to be divided 73 */ 74 phase = modulo; 75 } 76 } else { 77 /* 78 * set phase to 10 if dpp isn't used to 79 * prevent hard hang if access dpp register 80 * on unused pipe 81 * 82 * DTO should be on to divide down un-used 83 * pipe clock for power saving 84 */ 85 phase = 10; 86 } 87 88 REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0, 89 DPPCLK0_DTO_PHASE, phase, 90 DPPCLK0_DTO_MODULO, modulo); 91 92 REG_UPDATE(DPPCLK_DTO_CTRL, 93 DPPCLK_DTO_ENABLE[dpp_inst], 1); 94 } 95 96 dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk; 97 } 98 99 100 static const struct dccg_funcs dccg21_funcs = { 101 .update_dpp_dto = dccg21_update_dpp_dto, 102 .get_dccg_ref_freq = dccg2_get_dccg_ref_freq, 103 .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en, 104 .otg_add_pixel = dccg2_otg_add_pixel, 105 .otg_drop_pixel = dccg2_otg_drop_pixel, 106 .dccg_init = dccg2_init 107 }; 108 109 struct dccg *dccg21_create( 110 struct dc_context *ctx, 111 const struct dccg_registers *regs, 112 const struct dccg_shift *dccg_shift, 113 const struct dccg_mask *dccg_mask) 114 { 115 struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); 116 struct dccg *base; 117 118 if (dccg_dcn == NULL) { 119 BREAK_TO_DEBUGGER(); 120 return NULL; 121 } 122 123 base = &dccg_dcn->base; 124 base->ctx = ctx; 125 base->funcs = &dccg21_funcs; 126 127 dccg_dcn->regs = regs; 128 dccg_dcn->dccg_shift = dccg_shift; 129 dccg_dcn->dccg_mask = dccg_mask; 130 131 return &dccg_dcn->base; 132 } 133