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_hwseq.h"
0027 #include "reg_helper.h"
0028 #include "hw_sequencer_private.h"
0029 #include "core_types.h"
0030 
0031 #define CTX \
0032     hws->ctx
0033 #define REG(reg)\
0034     hws->regs->reg
0035 
0036 #undef FN
0037 #define FN(reg_name, field_name) \
0038     hws->shifts->field_name, hws->masks->field_name
0039 
0040 void dce_enable_fe_clock(struct dce_hwseq *hws,
0041         unsigned int fe_inst, bool enable)
0042 {
0043     REG_UPDATE(DCFE_CLOCK_CONTROL[fe_inst],
0044             DCFE_CLOCK_ENABLE, enable);
0045 }
0046 
0047 void dce_pipe_control_lock(struct dc *dc,
0048         struct pipe_ctx *pipe,
0049         bool lock)
0050 {
0051     uint32_t lock_val = lock ? 1 : 0;
0052     uint32_t dcp_grph, scl, blnd, update_lock_mode, val;
0053     struct dce_hwseq *hws = dc->hwseq;
0054 
0055     /* Not lock pipe when blank */
0056     if (lock && pipe->stream_res.tg->funcs->is_blanked &&
0057         pipe->stream_res.tg->funcs->is_blanked(pipe->stream_res.tg))
0058         return;
0059 
0060     val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst],
0061             BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph,
0062             BLND_SCL_V_UPDATE_LOCK, &scl,
0063             BLND_BLND_V_UPDATE_LOCK, &blnd,
0064             BLND_V_UPDATE_LOCK_MODE, &update_lock_mode);
0065 
0066     dcp_grph = lock_val;
0067     scl = lock_val;
0068     blnd = lock_val;
0069     update_lock_mode = lock_val;
0070 
0071     REG_SET_2(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst], val,
0072             BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph,
0073             BLND_SCL_V_UPDATE_LOCK, scl);
0074 
0075     if (hws->masks->BLND_BLND_V_UPDATE_LOCK != 0)
0076         REG_SET_2(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst], val,
0077                 BLND_BLND_V_UPDATE_LOCK, blnd,
0078                 BLND_V_UPDATE_LOCK_MODE, update_lock_mode);
0079 
0080     if (hws->wa.blnd_crtc_trigger) {
0081         if (!lock) {
0082             uint32_t value = REG_READ(CRTC_H_BLANK_START_END[pipe->stream_res.tg->inst]);
0083             REG_WRITE(CRTC_H_BLANK_START_END[pipe->stream_res.tg->inst], value);
0084         }
0085     }
0086 }
0087 
0088 #if defined(CONFIG_DRM_AMD_DC_SI)
0089 void dce60_pipe_control_lock(struct dc *dc,
0090         struct pipe_ctx *pipe,
0091         bool lock)
0092 {
0093     /* DCE6 has no BLND_V_UPDATE_LOCK register */
0094 }
0095 #endif
0096 
0097 void dce_set_blender_mode(struct dce_hwseq *hws,
0098     unsigned int blnd_inst,
0099     enum blnd_mode mode)
0100 {
0101     uint32_t feedthrough = 1;
0102     uint32_t blnd_mode = 0;
0103     uint32_t multiplied_mode = 0;
0104     uint32_t alpha_mode = 2;
0105 
0106     switch (mode) {
0107     case BLND_MODE_OTHER_PIPE:
0108         feedthrough = 0;
0109         blnd_mode = 1;
0110         alpha_mode = 0;
0111         break;
0112     case BLND_MODE_BLENDING:
0113         feedthrough = 0;
0114         blnd_mode = 2;
0115         alpha_mode = 0;
0116         multiplied_mode = 1;
0117         break;
0118     case BLND_MODE_CURRENT_PIPE:
0119     default:
0120         if (REG(BLND_CONTROL[blnd_inst]) == REG(BLNDV_CONTROL) ||
0121                 blnd_inst == 0)
0122             feedthrough = 0;
0123         break;
0124     }
0125 
0126     REG_UPDATE(BLND_CONTROL[blnd_inst],
0127         BLND_MODE, blnd_mode);
0128 
0129     if (hws->masks->BLND_ALPHA_MODE != 0) {
0130         REG_UPDATE_3(BLND_CONTROL[blnd_inst],
0131             BLND_FEEDTHROUGH_EN, feedthrough,
0132             BLND_ALPHA_MODE, alpha_mode,
0133             BLND_MULTIPLIED_MODE, multiplied_mode);
0134     }
0135 }
0136 
0137 
0138 static void dce_disable_sram_shut_down(struct dce_hwseq *hws)
0139 {
0140     if (REG(DC_MEM_GLOBAL_PWR_REQ_CNTL))
0141         REG_UPDATE(DC_MEM_GLOBAL_PWR_REQ_CNTL,
0142                 DC_MEM_GLOBAL_PWR_REQ_DIS, 1);
0143 }
0144 
0145 static void dce_underlay_clock_enable(struct dce_hwseq *hws)
0146 {
0147     /* todo: why do we need this at boot? is dce_enable_fe_clock enough? */
0148     if (REG(DCFEV_CLOCK_CONTROL))
0149         REG_UPDATE(DCFEV_CLOCK_CONTROL,
0150                 DCFEV_CLOCK_ENABLE, 1);
0151 }
0152 
0153 static void enable_hw_base_light_sleep(void)
0154 {
0155     /* TODO: implement */
0156 }
0157 
0158 static void disable_sw_manual_control_light_sleep(void)
0159 {
0160     /* TODO: implement */
0161 }
0162 
0163 void dce_clock_gating_power_up(struct dce_hwseq *hws,
0164         bool enable)
0165 {
0166     if (enable) {
0167         enable_hw_base_light_sleep();
0168         disable_sw_manual_control_light_sleep();
0169     } else {
0170         dce_disable_sram_shut_down(hws);
0171         dce_underlay_clock_enable(hws);
0172     }
0173 }
0174 
0175 void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws,
0176         struct clock_source *clk_src,
0177         unsigned int tg_inst)
0178 {
0179     if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO || clk_src->dp_clk_src) {
0180         REG_UPDATE(PIXEL_RATE_CNTL[tg_inst],
0181                 DP_DTO0_ENABLE, 1);
0182 
0183     } else if (clk_src->id >= CLOCK_SOURCE_COMBO_PHY_PLL0) {
0184         uint32_t rate_source = clk_src->id - CLOCK_SOURCE_COMBO_PHY_PLL0;
0185 
0186         REG_UPDATE_2(PHYPLL_PIXEL_RATE_CNTL[tg_inst],
0187                 PHYPLL_PIXEL_RATE_SOURCE, rate_source,
0188                 PIXEL_RATE_PLL_SOURCE, 0);
0189 
0190         REG_UPDATE(PIXEL_RATE_CNTL[tg_inst],
0191                 DP_DTO0_ENABLE, 0);
0192 
0193     } else if (clk_src->id <= CLOCK_SOURCE_ID_PLL2) {
0194         uint32_t rate_source = clk_src->id - CLOCK_SOURCE_ID_PLL0;
0195 
0196         REG_UPDATE_2(PIXEL_RATE_CNTL[tg_inst],
0197                 PIXEL_RATE_SOURCE, rate_source,
0198                 DP_DTO0_ENABLE, 0);
0199 
0200         if (REG(PHYPLL_PIXEL_RATE_CNTL[tg_inst]))
0201             REG_UPDATE(PHYPLL_PIXEL_RATE_CNTL[tg_inst],
0202                     PIXEL_RATE_PLL_SOURCE, 1);
0203     } else {
0204         DC_ERR("Unknown clock source. clk_src id: %d, TG_inst: %d",
0205                clk_src->id, tg_inst);
0206     }
0207 }
0208 
0209 /* Only use LUT for 8 bit formats */
0210 bool dce_use_lut(enum surface_pixel_format format)
0211 {
0212     switch (format) {
0213     case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
0214     case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
0215         return true;
0216     default:
0217         return false;
0218     }
0219 }