Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2018 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 "reg_helper.h"
0027 #include "core_types.h"
0028 #include "dcn20/dcn20_dccg.h"
0029 #include "dcn21_dccg.h"
0030 
0031 #define TO_DCN_DCCG(dccg)\
0032     container_of(dccg, struct dcn_dccg, base)
0033 
0034 #define REG(reg) \
0035     (dccg_dcn->regs->reg)
0036 
0037 #undef FN
0038 #define FN(reg_name, field_name) \
0039     dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name
0040 
0041 #define CTX \
0042     dccg_dcn->base.ctx
0043 #define DC_LOGGER \
0044     dccg->ctx->logger
0045 
0046 void dccg21_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk)
0047 {
0048     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0049 
0050     if (dccg->ref_dppclk) {
0051         int ref_dppclk = dccg->ref_dppclk;
0052         int modulo = ref_dppclk / 10000;
0053         int phase;
0054 
0055         if (req_dppclk) {
0056             /*
0057              * program DPP DTO phase and modulo as below
0058              * phase = ceiling(dpp_pipe_clk_mhz / 10)
0059              * module = trunc(dpp_global_clk_mhz / 10)
0060              *
0061              * storing frequencies in registers allow dmcub fw
0062              * to run time lower clocks when possible for power saving
0063              *
0064              * ceiling phase and truncate modulo guarentees the divided
0065              * down per pipe dpp clock has high enough frequency
0066              */
0067             phase = (req_dppclk + 9999) / 10000;
0068 
0069             if (phase > modulo) {
0070                 /* phase > modulo result in screen corruption
0071                  * ie phase = 30, mod = 29 for 4k@60 HDMI
0072                  * in these case we don't want pipe clock to be divided
0073                  */
0074                 phase = modulo;
0075             }
0076         } else {
0077             /*
0078              *  set phase to 10 if dpp isn't used to
0079              *  prevent hard hang if access dpp register
0080              *  on unused pipe
0081              *
0082              *  DTO should be on to divide down un-used
0083              *  pipe clock for power saving
0084              */
0085             phase = 10;
0086         }
0087 
0088         REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
0089                 DPPCLK0_DTO_PHASE, phase,
0090                 DPPCLK0_DTO_MODULO, modulo);
0091 
0092         REG_UPDATE(DPPCLK_DTO_CTRL,
0093                 DPPCLK_DTO_ENABLE[dpp_inst], 1);
0094     }
0095 
0096     dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
0097 }
0098 
0099 
0100 static const struct dccg_funcs dccg21_funcs = {
0101     .update_dpp_dto = dccg21_update_dpp_dto,
0102     .get_dccg_ref_freq = dccg2_get_dccg_ref_freq,
0103     .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
0104     .otg_add_pixel = dccg2_otg_add_pixel,
0105     .otg_drop_pixel = dccg2_otg_drop_pixel,
0106     .dccg_init = dccg2_init
0107 };
0108 
0109 struct dccg *dccg21_create(
0110     struct dc_context *ctx,
0111     const struct dccg_registers *regs,
0112     const struct dccg_shift *dccg_shift,
0113     const struct dccg_mask *dccg_mask)
0114 {
0115     struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
0116     struct dccg *base;
0117 
0118     if (dccg_dcn == NULL) {
0119         BREAK_TO_DEBUGGER();
0120         return NULL;
0121     }
0122 
0123     base = &dccg_dcn->base;
0124     base->ctx = ctx;
0125     base->funcs = &dccg21_funcs;
0126 
0127     dccg_dcn->regs = regs;
0128     dccg_dcn->dccg_shift = dccg_shift;
0129     dccg_dcn->dccg_mask = dccg_mask;
0130 
0131     return &dccg_dcn->base;
0132 }