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 "dm_services.h"
0027 #include "dm_helpers.h"
0028 #include "core_types.h"
0029 #include "resource.h"
0030 #include "dce/dce_hwseq.h"
0031 #include "dce110/dce110_hw_sequencer.h"
0032 #include "dcn21_hwseq.h"
0033 #include "vmid.h"
0034 #include "reg_helper.h"
0035 #include "hw/clk_mgr.h"
0036 #include "dc_dmub_srv.h"
0037 #include "abm.h"
0038 
0039 
0040 #define DC_LOGGER_INIT(logger)
0041 
0042 #define CTX \
0043     hws->ctx
0044 #define REG(reg)\
0045     hws->regs->reg
0046 
0047 #undef FN
0048 #define FN(reg_name, field_name) \
0049     hws->shifts->field_name, hws->masks->field_name
0050 
0051 /* Temporary read settings, future will get values from kmd directly */
0052 static void mmhub_update_page_table_config(struct dcn_hubbub_phys_addr_config *config,
0053         struct dce_hwseq *hws)
0054 {
0055     uint32_t page_table_base_hi;
0056     uint32_t page_table_base_lo;
0057 
0058     REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
0059             PAGE_DIRECTORY_ENTRY_HI32, &page_table_base_hi);
0060     REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
0061             PAGE_DIRECTORY_ENTRY_LO32, &page_table_base_lo);
0062 
0063     config->gart_config.page_table_base_addr = ((uint64_t)page_table_base_hi << 32) | page_table_base_lo;
0064 
0065 }
0066 
0067 int dcn21_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config)
0068 {
0069     struct dcn_hubbub_phys_addr_config config;
0070 
0071     config.system_aperture.fb_top = pa_config->system_aperture.fb_top;
0072     config.system_aperture.fb_offset = pa_config->system_aperture.fb_offset;
0073     config.system_aperture.fb_base = pa_config->system_aperture.fb_base;
0074     config.system_aperture.agp_top = pa_config->system_aperture.agp_top;
0075     config.system_aperture.agp_bot = pa_config->system_aperture.agp_bot;
0076     config.system_aperture.agp_base = pa_config->system_aperture.agp_base;
0077     config.gart_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr;
0078     config.gart_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr;
0079     config.gart_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
0080 
0081     mmhub_update_page_table_config(&config, hws);
0082 
0083     return dc->res_pool->hubbub->funcs->init_dchub_sys_ctx(dc->res_pool->hubbub, &config);
0084 }
0085 
0086 // work around for Renoir s0i3, if register is programmed, bypass golden init.
0087 
0088 bool dcn21_s0i3_golden_init_wa(struct dc *dc)
0089 {
0090     struct dce_hwseq *hws = dc->hwseq;
0091     uint32_t value = 0;
0092 
0093     value = REG_READ(MICROSECOND_TIME_BASE_DIV);
0094 
0095     return value != 0x00120464;
0096 }
0097 
0098 void dcn21_exit_optimized_pwr_state(
0099         const struct dc *dc,
0100         struct dc_state *context)
0101 {
0102     dc->clk_mgr->funcs->update_clocks(
0103             dc->clk_mgr,
0104             context,
0105             false);
0106 }
0107 
0108 void dcn21_optimize_pwr_state(
0109         const struct dc *dc,
0110         struct dc_state *context)
0111 {
0112     dc->clk_mgr->funcs->update_clocks(
0113             dc->clk_mgr,
0114             context,
0115             true);
0116 }
0117 
0118 /* If user hotplug a HDMI monitor while in monitor off,
0119  * OS will do a mode set (with output timing) but keep output off.
0120  * In this case DAL will ask vbios to power up the pll in the PHY.
0121  * If user unplug the monitor (while we are on monitor off) or
0122  * system attempt to enter modern standby (which we will disable PLL),
0123  * PHY will hang on the next mode set attempt.
0124  * if enable PLL follow by disable PLL (without executing lane enable/disable),
0125  * RDPCS_PHY_DP_MPLLB_STATE remains 1,
0126  * which indicate that PLL disable attempt actually didn't go through.
0127  * As a workaround, insert PHY lane enable/disable before PLL disable.
0128  */
0129 void dcn21_PLAT_58856_wa(struct dc_state *context, struct pipe_ctx *pipe_ctx)
0130 {
0131     if (!pipe_ctx->stream->dpms_off)
0132         return;
0133 
0134     pipe_ctx->stream->dpms_off = false;
0135     core_link_enable_stream(context, pipe_ctx);
0136     core_link_disable_stream(pipe_ctx);
0137     pipe_ctx->stream->dpms_off = true;
0138 }
0139 
0140 static bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst)
0141 {
0142     union dmub_rb_cmd cmd;
0143     struct dc_context *dc = abm->ctx;
0144     uint32_t ramping_boundary = 0xFFFF;
0145 
0146     memset(&cmd, 0, sizeof(cmd));
0147     cmd.abm_set_pipe.header.type = DMUB_CMD__ABM;
0148     cmd.abm_set_pipe.header.sub_type = DMUB_CMD__ABM_SET_PIPE;
0149     cmd.abm_set_pipe.abm_set_pipe_data.otg_inst = otg_inst;
0150     cmd.abm_set_pipe.abm_set_pipe_data.set_pipe_option = option;
0151     cmd.abm_set_pipe.abm_set_pipe_data.panel_inst = panel_inst;
0152     cmd.abm_set_pipe.abm_set_pipe_data.ramping_boundary = ramping_boundary;
0153     cmd.abm_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pipe_data);
0154 
0155     dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
0156     dc_dmub_srv_cmd_execute(dc->dmub_srv);
0157     dc_dmub_srv_wait_idle(dc->dmub_srv);
0158 
0159     return true;
0160 }
0161 
0162 void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx)
0163 {
0164     struct abm *abm = pipe_ctx->stream_res.abm;
0165     uint32_t otg_inst = pipe_ctx->stream_res.tg->inst;
0166     struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
0167 
0168     struct dmcu *dmcu = pipe_ctx->stream->ctx->dc->res_pool->dmcu;
0169 
0170     if (dmcu) {
0171         dce110_set_abm_immediate_disable(pipe_ctx);
0172         return;
0173     }
0174 
0175     if (abm && panel_cntl) {
0176         dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_IMMEDIATELY_DISABLE,
0177                 panel_cntl->inst);
0178         panel_cntl->funcs->store_backlight_level(panel_cntl);
0179     }
0180 }
0181 
0182 void dcn21_set_pipe(struct pipe_ctx *pipe_ctx)
0183 {
0184     struct abm *abm = pipe_ctx->stream_res.abm;
0185     uint32_t otg_inst = pipe_ctx->stream_res.tg->inst;
0186     struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
0187     struct dmcu *dmcu = pipe_ctx->stream->ctx->dc->res_pool->dmcu;
0188 
0189     if (dmcu) {
0190         dce110_set_pipe(pipe_ctx);
0191         return;
0192     }
0193 
0194     if (abm && panel_cntl)
0195         dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_NORMAL, panel_cntl->inst);
0196 }
0197 
0198 bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx,
0199         uint32_t backlight_pwm_u16_16,
0200         uint32_t frame_ramp)
0201 {
0202     union dmub_rb_cmd cmd;
0203     struct dc_context *dc = pipe_ctx->stream->ctx;
0204     struct abm *abm = pipe_ctx->stream_res.abm;
0205     uint32_t otg_inst = pipe_ctx->stream_res.tg->inst;
0206     struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
0207 
0208     if (dc->dc->res_pool->dmcu) {
0209         dce110_set_backlight_level(pipe_ctx, backlight_pwm_u16_16, frame_ramp);
0210         return true;
0211     }
0212 
0213     if (abm && panel_cntl)
0214         dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_NORMAL, panel_cntl->inst);
0215 
0216     memset(&cmd, 0, sizeof(cmd));
0217     cmd.abm_set_backlight.header.type = DMUB_CMD__ABM;
0218     cmd.abm_set_backlight.header.sub_type = DMUB_CMD__ABM_SET_BACKLIGHT;
0219     cmd.abm_set_backlight.abm_set_backlight_data.frame_ramp = frame_ramp;
0220     cmd.abm_set_backlight.abm_set_backlight_data.backlight_user_level = backlight_pwm_u16_16;
0221     cmd.abm_set_backlight.abm_set_backlight_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
0222     cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_cntl->inst);
0223     cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data);
0224 
0225     dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
0226     dc_dmub_srv_cmd_execute(dc->dmub_srv);
0227     dc_dmub_srv_wait_idle(dc->dmub_srv);
0228 
0229     return true;
0230 }
0231 
0232 bool dcn21_is_abm_supported(struct dc *dc,
0233         struct dc_state *context, struct dc_stream_state *stream)
0234 {
0235     int i;
0236 
0237     for (i = 0; i < dc->res_pool->pipe_count; i++) {
0238         struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
0239 
0240         if (pipe_ctx->stream == stream &&
0241                 (pipe_ctx->prev_odm_pipe == NULL && pipe_ctx->next_odm_pipe == NULL))
0242             return true;
0243     }
0244     return false;
0245 }
0246