diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dce')
21 files changed, 548 insertions, 246 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile index 6d7b64a743ca..fdf3d8f87eee 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile @@ -28,7 +28,7 @@ DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \ -dce_clk_mgr.o dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o dce_aux.o \ +dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o dce_aux.o \ dce_i2c.o dce_i2c_hw.o dce_i2c_sw.o AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index da96229db53a..58bd131d5b48 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -23,6 +23,8 @@ * */ +#include <linux/slab.h> + #include "dce_abm.h" #include "dm_services.h" #include "reg_helper.h" @@ -58,6 +60,9 @@ static bool dce_abm_set_pipe(struct abm *abm, uint32_t controller_id) struct dce_abm *abm_dce = TO_DCE_ABM(abm); uint32_t rampingBoundary = 0xFFFF; + if (abm->dmcu_is_running == false) + return true; + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 80000); @@ -234,6 +239,10 @@ static void dmcu_set_backlight_level( s2 |= (backlight_8_bit << ATOM_S2_CURRENT_BL_LEVEL_SHIFT); REG_WRITE(BIOS_SCRATCH_2, s2); + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, + 0, 1, 80000); } static void dce_abm_init(struct abm *abm) @@ -302,6 +311,9 @@ static bool dce_abm_set_level(struct abm *abm, uint32_t level) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); + if (abm->dmcu_is_running == false) + return true; + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 80000); @@ -320,6 +332,9 @@ static bool dce_abm_immediate_disable(struct abm *abm) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); + if (abm->dmcu_is_running == false) + return true; + dce_abm_set_pipe(abm, MCP_DISABLE_ABM_IMMEDIATELY); abm->stored_backlight_registers.BL_PWM_CNTL = @@ -443,6 +458,7 @@ static void dce_abm_construct( base->stored_backlight_registers.BL_PWM_CNTL2 = 0; base->stored_backlight_registers.BL_PWM_PERIOD_CNTL = 0; base->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV = 0; + base->dmcu_is_running = false; abm_dce->regs = regs; abm_dce->abm_shift = abm_shift; @@ -473,6 +489,9 @@ void dce_abm_destroy(struct abm **abm) { struct dce_abm *abm_dce = TO_DCE_ABM(*abm); + if (abm_dce->base.dmcu_is_running == true) + abm_dce->base.funcs->set_abm_immediate_disable(*abm); + kfree(abm_dce); *abm = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index ff9436966041..7ba7e6f722f6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -67,6 +67,22 @@ SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ NBIO_SR(BIOS_SCRATCH_2) +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +#define ABM_DCN20_REG_LIST() \ + ABM_COMMON_REG_LIST_DCE_BASE(), \ + SR(DC_ABM1_HG_SAMPLE_RATE), \ + SR(DC_ABM1_LS_SAMPLE_RATE), \ + SR(BL1_PWM_BL_UPDATE_SAMPLE_RATE), \ + SR(DC_ABM1_HG_MISC_CTRL), \ + SR(DC_ABM1_IPCSC_COEFF_SEL), \ + SR(BL1_PWM_CURRENT_ABM_LEVEL), \ + SR(BL1_PWM_TARGET_ABM_LEVEL), \ + SR(BL1_PWM_USER_LEVEL), \ + SR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES), \ + SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \ + NBIO_SR(BIOS_SCRATCH_2) +#endif + #define ABM_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -147,6 +163,10 @@ ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +#define ABM_MASK_SH_LIST_DCN20(mask_sh) ABM_MASK_SH_LIST_DCE110(mask_sh) +#endif + #define ABM_REG_FIELD_LIST(type) \ type ABM1_HG_NUM_OF_BINS_SEL; \ type ABM1_HG_VMAX_SEL; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 7f6d724686f1..4a10a5d22c90 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -23,6 +23,8 @@ * */ +#include <linux/slab.h> + #include "reg_helper.h" #include "dce_audio.h" #include "dce/dce_11_0_d.h" @@ -841,8 +843,6 @@ void dce_aud_wall_dto_setup( REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, 1); - REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, - DCCG_AUDIO_DTO_SEL, 1); /* DCCG_AUDIO_DTO2_USE_512FBR_DTO, 1) * Select 512fs for DP TODO: web register definition * does not match register header file diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h index 0dc5ff137c7a..a0d5724aab31 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h @@ -49,6 +49,8 @@ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO2_USE_512FBR_DTO, mask_sh),\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_USE_512FBR_DTO, mask_sh),\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO1_USE_512FBR_DTO, mask_sh),\ SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\ SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\ SF(DCCG_AUDIO_DTO1_MODULE, DCCG_AUDIO_DTO1_MODULE, mask_sh),\ @@ -95,6 +97,8 @@ struct dce_audio_shift { uint8_t DCCG_AUDIO_DTO1_MODULE; uint8_t DCCG_AUDIO_DTO1_PHASE; uint8_t DCCG_AUDIO_DTO2_USE_512FBR_DTO; + uint32_t DCCG_AUDIO_DTO0_USE_512FBR_DTO; + uint32_t DCCG_AUDIO_DTO1_USE_512FBR_DTO; }; struct dce_aduio_mask { @@ -112,6 +116,9 @@ struct dce_aduio_mask { uint32_t DCCG_AUDIO_DTO1_MODULE; uint32_t DCCG_AUDIO_DTO1_PHASE; uint32_t DCCG_AUDIO_DTO2_USE_512FBR_DTO; + uint32_t DCCG_AUDIO_DTO0_USE_512FBR_DTO; + uint32_t DCCG_AUDIO_DTO1_USE_512FBR_DTO; + }; struct dce_audio { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index bd33c47183fc..f2295e780031 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -23,6 +23,9 @@ * */ +#include <linux/delay.h> +#include <linux/slab.h> + #include "dm_services.h" #include "core_types.h" #include "dce_aux.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h index ce6a26d189b0..ed7fec8fe253 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h @@ -29,6 +29,16 @@ #include "i2caux_interface.h" #include "inc/hw/aux_engine.h" +#ifdef CONFIG_DRM_AMD_DC_DCN2_0 +#define AUX_COMMON_REG_LIST0(id)\ + SRI(AUX_CONTROL, DP_AUX, id), \ + SRI(AUX_ARB_CONTROL, DP_AUX, id), \ + SRI(AUX_SW_DATA, DP_AUX, id), \ + SRI(AUX_SW_CONTROL, DP_AUX, id), \ + SRI(AUX_INTERRUPT_CONTROL, DP_AUX, id), \ + SRI(AUX_SW_STATUS, DP_AUX, id) +#endif + #define AUX_COMMON_REG_LIST(id)\ SRI(AUX_CONTROL, DP_AUX, id), \ SRI(AUX_ARB_CONTROL, DP_AUX, id), \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c index 963686380738..29d69dfc9848 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c @@ -23,6 +23,8 @@ * */ +#include <linux/slab.h> + #include "dce_clk_mgr.h" #include "reg_helper.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.h deleted file mode 100644 index c8f8c442142a..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2012-16 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - - -#ifndef _DCE_CLK_MGR_H_ -#define _DCE_CLK_MGR_H_ - -#include "clk_mgr.h" -#include "dccg.h" - -#define MEMORY_TYPE_MULTIPLIER_CZ 4 - -#define CLK_COMMON_REG_LIST_DCE_BASE() \ - .DPREFCLK_CNTL = mmDPREFCLK_CNTL, \ - .DENTIST_DISPCLK_CNTL = mmDENTIST_DISPCLK_CNTL - -#define CLK_COMMON_REG_LIST_DCN_BASE() \ - SR(DENTIST_DISPCLK_CNTL) - -#define CLK_SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ - CLK_SF(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ - CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh) - -#define CLK_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(mask_sh) \ - CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\ - CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh) - -#define CLK_REG_FIELD_LIST(type) \ - type DPREFCLK_SRC_SEL; \ - type DENTIST_DPREFCLK_WDIVIDER; \ - type DENTIST_DISPCLK_WDIVIDER; \ - type DENTIST_DISPCLK_CHG_DONE; - -struct clk_mgr_shift { - CLK_REG_FIELD_LIST(uint8_t) -}; - -struct clk_mgr_mask { - CLK_REG_FIELD_LIST(uint32_t) -}; - -struct clk_mgr_registers { - uint32_t DPREFCLK_CNTL; - uint32_t DENTIST_DISPCLK_CNTL; -}; - -struct state_dependent_clocks { - int display_clk_khz; - int pixel_clk_khz; -}; - -struct dce_clk_mgr { - struct clk_mgr base; - const struct clk_mgr_registers *regs; - const struct clk_mgr_shift *clk_mgr_shift; - const struct clk_mgr_mask *clk_mgr_mask; - - struct dccg *dccg; - - struct state_dependent_clocks max_clks_by_state[DM_PP_CLOCKS_MAX_STATES]; - - int dentist_vco_freq_khz; - - /* Cache the status of DFS-bypass feature*/ - bool dfs_bypass_enabled; - /* True if the DFS-bypass feature is enabled and active. */ - bool dfs_bypass_active; - /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. - * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ - int dfs_bypass_disp_clk; - - /** - * @ss_on_dprefclk: - * - * True if spread spectrum is enabled on the DP ref clock. - */ - bool ss_on_dprefclk; - - /** - * @xgmi_enabled: - * - * True if xGMI is enabled. On VG20, both audio and display clocks need - * to be adjusted with the WAFL link's SS info if xGMI is enabled. - */ - bool xgmi_enabled; - - /** - * @dprefclk_ss_percentage: - * - * DPREFCLK SS percentage (if down-spread enabled). - * - * Note that if XGMI is enabled, the SS info (percentage and divider) - * from the WAFL link is used instead. This is decided during - * dce_clk_mgr initialization. - */ - int dprefclk_ss_percentage; - - /** - * @dprefclk_ss_divider: - * - * DPREFCLK SS percentage Divider (100 or 1000). - */ - int dprefclk_ss_divider; - int dprefclk_khz; - - enum dm_pp_clocks_state max_clks_state; - enum dm_pp_clocks_state cur_min_clks_state; -}; - -/* Starting DID for each range */ -enum dentist_base_divider_id { - DENTIST_BASE_DID_1 = 0x08, - DENTIST_BASE_DID_2 = 0x40, - DENTIST_BASE_DID_3 = 0x60, - DENTIST_BASE_DID_4 = 0x7e, - DENTIST_MAX_DID = 0x7f -}; - -/* Starting point and step size for each divider range.*/ -enum dentist_divider_range { - DENTIST_DIVIDER_RANGE_1_START = 8, /* 2.00 */ - DENTIST_DIVIDER_RANGE_1_STEP = 1, /* 0.25 */ - DENTIST_DIVIDER_RANGE_2_START = 64, /* 16.00 */ - DENTIST_DIVIDER_RANGE_2_STEP = 2, /* 0.50 */ - DENTIST_DIVIDER_RANGE_3_START = 128, /* 32.00 */ - DENTIST_DIVIDER_RANGE_3_STEP = 4, /* 1.00 */ - DENTIST_DIVIDER_RANGE_4_START = 248, /* 62.00 */ - DENTIST_DIVIDER_RANGE_4_STEP = 264, /* 66.00 */ - DENTIST_DIVIDER_RANGE_SCALE_FACTOR = 4 -}; - -static inline bool should_set_clock(bool safe_to_lower, int calc_clk, int cur_clk) -{ - return ((safe_to_lower && calc_clk < cur_clk) || calc_clk > cur_clk); -} - -void dce_clock_read_ss_info(struct dce_clk_mgr *dccg_dce); - -int dce12_get_dp_ref_freq_khz(struct clk_mgr *dccg); - -void dce110_fill_display_configs( - const struct dc_state *context, - struct dm_pp_display_configuration *pp_display_cfg); - -int dce112_set_clock(struct clk_mgr *dccg, int requested_clk_khz); - -struct clk_mgr *dce_clk_mgr_create( - struct dc_context *ctx, - const struct clk_mgr_registers *regs, - const struct clk_mgr_shift *clk_shift, - const struct clk_mgr_mask *clk_mask); - -struct clk_mgr *dce110_clk_mgr_create( - struct dc_context *ctx, - const struct clk_mgr_registers *regs, - const struct clk_mgr_shift *clk_shift, - const struct clk_mgr_mask *clk_mask); - -struct clk_mgr *dce112_clk_mgr_create( - struct dc_context *ctx, - const struct clk_mgr_registers *regs, - const struct clk_mgr_shift *clk_shift, - const struct clk_mgr_mask *clk_mask); - -struct clk_mgr *dce120_clk_mgr_create(struct dc_context *ctx); - -struct clk_mgr *dce121_clk_mgr_create(struct dc_context *ctx); -void dce121_clock_patch_xgmi_ss_info(struct clk_mgr *clk_mgr); - -void dce_clk_mgr_destroy(struct clk_mgr **clk_mgr); - -int dentist_get_divider_from_did(int did); - -#endif /* _DCE_CLK_MGR_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index f70437aae8e0..5fae77e201d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -23,6 +23,8 @@ * */ +#include <linux/slab.h> + #include "dm_services.h" @@ -33,6 +35,7 @@ #include "include/logger_interface.h" #include "dce_clock_source.h" +#include "clk_mgr.h" #include "reg_helper.h" @@ -52,6 +55,8 @@ #define CALC_PLL_CLK_SRC_ERR_TOLERANCE 1 #define MAX_PLL_CALC_ERROR 0xFFFFFFFF +#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) + static const struct spread_spectrum_data *get_ss_data_entry( struct dce110_clk_src *clk_src, enum signal_type signal, @@ -183,8 +188,8 @@ static bool calculate_fb_and_fractional_fb_divider( *RETURNS: * It fills the PLLSettings structure with PLL Dividers values * if calculated values are within required tolerance -* It returns - true if eror is within tolerance -* - false if eror is not within tolerance +* It returns - true if error is within tolerance +* - false if error is not within tolerance */ static bool calc_fb_divider_checking_tolerance( struct calc_pll_clock_source *calc_pll_cs, @@ -999,6 +1004,67 @@ static bool get_pixel_clk_frequency_100hz( return false; } +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) + +/* this table is use to find *1.001 and /1.001 pixel rates from non-precise pixel rate */ +struct pixel_rate_range_table_entry { + unsigned int range_min_khz; + unsigned int range_max_khz; + unsigned int target_pixel_rate_khz; + unsigned short mult_factor; + unsigned short div_factor; +}; + +static const struct pixel_rate_range_table_entry video_optimized_pixel_rates[] = { + // /1.001 rates + {25170, 25180, 25200, 1000, 1001}, //25.2MHz -> 25.17 + {59340, 59350, 59400, 1000, 1001}, //59.4Mhz -> 59.340 + {74170, 74180, 74250, 1000, 1001}, //74.25Mhz -> 74.1758 + {125870, 125880, 126000, 1000, 1001}, //126Mhz -> 125.87 + {148350, 148360, 148500, 1000, 1001}, //148.5Mhz -> 148.3516 + {167830, 167840, 168000, 1000, 1001}, //168Mhz -> 167.83 + {222520, 222530, 222750, 1000, 1001}, //222.75Mhz -> 222.527 + {257140, 257150, 257400, 1000, 1001}, //257.4Mhz -> 257.1429 + {296700, 296710, 297000, 1000, 1001}, //297Mhz -> 296.7033 + {342850, 342860, 343200, 1000, 1001}, //343.2Mhz -> 342.857 + {395600, 395610, 396000, 1000, 1001}, //396Mhz -> 395.6 + {409090, 409100, 409500, 1000, 1001}, //409.5Mhz -> 409.091 + {445050, 445060, 445500, 1000, 1001}, //445.5Mhz -> 445.055 + {467530, 467540, 468000, 1000, 1001}, //468Mhz -> 467.5325 + {519230, 519240, 519750, 1000, 1001}, //519.75Mhz -> 519.231 + {525970, 525980, 526500, 1000, 1001}, //526.5Mhz -> 525.974 + {545450, 545460, 546000, 1000, 1001}, //546Mhz -> 545.455 + {593400, 593410, 594000, 1000, 1001}, //594Mhz -> 593.4066 + {623370, 623380, 624000, 1000, 1001}, //624Mhz -> 623.377 + {692300, 692310, 693000, 1000, 1001}, //693Mhz -> 692.308 + {701290, 701300, 702000, 1000, 1001}, //702Mhz -> 701.2987 + {791200, 791210, 792000, 1000, 1001}, //792Mhz -> 791.209 + {890100, 890110, 891000, 1000, 1001}, //891Mhz -> 890.1099 + {1186810, 1186820, 1188000, 1000, 1001},//1188Mhz -> 1186.8131 + + // *1.001 rates + {27020, 27030, 27000, 1001, 1000}, //27Mhz + {54050, 54060, 54000, 1001, 1000}, //54Mhz + {108100, 108110, 108000, 1001, 1000},//108Mhz +}; + +static bool dcn20_program_pix_clk( + struct clock_source *clock_source, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + dce112_program_pix_clk(clock_source, pix_clk_params, pll_settings); + + return true; +} + +static const struct clock_source_funcs dcn20_clk_src_funcs = { + .cs_power_down = dce110_clock_source_power_down, + .program_pix_clk = dcn20_program_pix_clk, + .get_pix_clk_dividers = dce112_get_pix_clk_dividers +}; +#endif + /*****************************************/ /* Constructor */ /*****************************************/ @@ -1375,3 +1441,20 @@ bool dce112_clk_src_construct( return true; } +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +bool dcn20_clk_src_construct( + struct dce110_clk_src *clk_src, + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + const struct dce110_clk_src_shift *cs_shift, + const struct dce110_clk_src_mask *cs_mask) +{ + bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask); + + clk_src->base.funcs = &dcn20_clk_src_funcs; + + return ret; +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index 1ed7695a76d3..adae03b1f3a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -55,6 +55,37 @@ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +#define CS_COMMON_REG_LIST_DCN2_0(index, pllid) \ + SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\ + SRII(PHASE, DP_DTO, 0),\ + SRII(PHASE, DP_DTO, 1),\ + SRII(PHASE, DP_DTO, 2),\ + SRII(PHASE, DP_DTO, 3),\ + SRII(PHASE, DP_DTO, 4),\ + SRII(PHASE, DP_DTO, 5),\ + SRII(MODULO, DP_DTO, 0),\ + SRII(MODULO, DP_DTO, 1),\ + SRII(MODULO, DP_DTO, 2),\ + SRII(MODULO, DP_DTO, 3),\ + SRII(MODULO, DP_DTO, 4),\ + SRII(MODULO, DP_DTO, 5),\ + SRII(PIXEL_RATE_CNTL, OTG, 0),\ + SRII(PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PIXEL_RATE_CNTL, OTG, 3),\ + SRII(PIXEL_RATE_CNTL, OTG, 4),\ + SRII(PIXEL_RATE_CNTL, OTG, 5) +#endif + +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +#define CS_COMMON_MASK_SH_LIST_DCN2_0(mask_sh)\ + CS_SF(DP_DTO0_PHASE, DP_DTO0_PHASE, mask_sh),\ + CS_SF(DP_DTO0_MODULO, DP_DTO0_MODULO, mask_sh),\ + CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ + CS_SF(OTG0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh) +#endif + #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define CS_COMMON_REG_LIST_DCN1_0(index, pllid) \ @@ -153,4 +184,15 @@ bool dce112_clk_src_construct( const struct dce110_clk_src_shift *cs_shift, const struct dce110_clk_src_mask *cs_mask); +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +bool dcn20_clk_src_construct( + struct dce110_clk_src *clk_src, + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + const struct dce110_clk_src_shift *cs_shift, + const struct dce110_clk_src_mask *cs_mask); +#endif + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 818536eea00a..0b86cee4876f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -23,6 +23,9 @@ * */ +#include <linux/delay.h> +#include <linux/slab.h> + #include "core_types.h" #include "link_encoder.h" #include "dce_dmcu.h" @@ -388,6 +391,9 @@ static bool dcn10_dmcu_init(struct dmcu *dmcu) /* Set initialized ramping boundary value */ REG_WRITE(MASTER_COMM_DATA_REG1, 0xFFFF); + /* Set backlight ramping stepsize */ + REG_WRITE(MASTER_COMM_DATA_REG2, abm_gain_stepsize); + /* Set command to initialize microcontroller */ REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_INIT_DMCU); @@ -723,6 +729,56 @@ static bool dcn10_is_dmcu_initialized(struct dmcu *dmcu) #endif //(CONFIG_DRM_AMD_DC_DCN1_0) +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) + +static bool dcn20_lock_phy(struct dmcu *dmcu) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + + /* If microcontroller is not running, do nothing */ + if (dmcu->dmcu_state != DMCU_RUNNING) + return false; + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_SYNC_PHY_LOCK); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); + + return true; +} + +static bool dcn20_unlock_phy(struct dmcu *dmcu) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + + /* If microcontroller is not running, do nothing */ + if (dmcu->dmcu_state != DMCU_RUNNING) + return false; + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_SYNC_PHY_UNLOCK); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); + + return true; +} + +#endif //(CONFIG_DRM_AMD_DC_DCN2_0) + static const struct dmcu_funcs dce_funcs = { .dmcu_init = dce_dmcu_init, .load_iram = dce_dmcu_load_iram, @@ -747,6 +803,21 @@ static const struct dmcu_funcs dcn10_funcs = { }; #endif +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +static const struct dmcu_funcs dcn20_funcs = { + .dmcu_init = dcn10_dmcu_init, + .load_iram = dcn10_dmcu_load_iram, + .set_psr_enable = dcn10_dmcu_set_psr_enable, + .setup_psr = dcn10_dmcu_setup_psr, + .get_psr_state = dcn10_get_dmcu_psr_state, + .set_psr_wait_loop = dcn10_psr_wait_loop, + .get_psr_wait_loop = dcn10_get_psr_wait_loop, + .is_dmcu_initialized = dcn10_is_dmcu_initialized, + .lock_phy = dcn20_lock_phy, + .unlock_phy = dcn20_unlock_phy +}; +#endif + static void dce_dmcu_construct( struct dce_dmcu *dmcu_dce, struct dc_context *ctx, @@ -809,10 +880,36 @@ struct dmcu *dcn10_dmcu_create( } #endif +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +struct dmcu *dcn20_dmcu_create( + struct dc_context *ctx, + const struct dce_dmcu_registers *regs, + const struct dce_dmcu_shift *dmcu_shift, + const struct dce_dmcu_mask *dmcu_mask) +{ + struct dce_dmcu *dmcu_dce = kzalloc(sizeof(*dmcu_dce), GFP_KERNEL); + + if (dmcu_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_dmcu_construct( + dmcu_dce, ctx, regs, dmcu_shift, dmcu_mask); + + dmcu_dce->base.funcs = &dcn20_funcs; + + return &dmcu_dce->base; +} +#endif + void dce_dmcu_destroy(struct dmcu **dmcu) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(*dmcu); + if (dmcu_dce->base.dmcu_state == DMCU_RUNNING) + dmcu_dce->base.funcs->set_psr_enable(*dmcu, false, true); + kfree(dmcu_dce); *dmcu = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index 60ce56f60ae3..cc8587683b4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -261,6 +261,16 @@ struct dmcu *dcn10_dmcu_create( const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask); +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +struct dmcu *dcn20_dmcu_create( + struct dc_context *ctx, + const struct dce_dmcu_registers *regs, + const struct dce_dmcu_shift *dmcu_shift, + const struct dce_dmcu_mask *dmcu_mask); +#endif + void dce_dmcu_destroy(struct dmcu **dmcu); +static const uint32_t abm_gain_stepsize = 0x0060; + #endif /* _DCE_ABM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 956bdf14503f..cb0a037b1c4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -199,6 +199,70 @@ SR(DC_IP_REQUEST_CNTL), \ BL_REG_LIST() +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +#define HWSEQ_DCN2_REG_LIST()\ + HWSEQ_DCN_REG_LIST(), \ + HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ + HWSEQ_PHYPLL_REG_LIST(OTG), \ + SR(MICROSECOND_TIME_BASE_DIV), \ + SR(MILLISECOND_TIME_BASE_DIV), \ + SR(DISPCLK_FREQ_CHANGE_CNTL), \ + SR(RBBMIF_TIMEOUT_DIS), \ + SR(RBBMIF_TIMEOUT_DIS_2), \ + SR(DCHUBBUB_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ + SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ + SR(MPC_CRC_CTRL), \ + SR(MPC_CRC_RESULT_GB), \ + SR(MPC_CRC_RESULT_C), \ + SR(MPC_CRC_RESULT_AR), \ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN4_PG_CONFIG), \ + SR(DOMAIN5_PG_CONFIG), \ + SR(DOMAIN6_PG_CONFIG), \ + SR(DOMAIN7_PG_CONFIG), \ + SR(DOMAIN8_PG_CONFIG), \ + SR(DOMAIN9_PG_CONFIG), \ + SR(DOMAIN10_PG_CONFIG), \ + SR(DOMAIN11_PG_CONFIG), \ + SR(DOMAIN16_PG_CONFIG), \ + SR(DOMAIN17_PG_CONFIG), \ + SR(DOMAIN18_PG_CONFIG), \ + SR(DOMAIN19_PG_CONFIG), \ + SR(DOMAIN20_PG_CONFIG), \ + SR(DOMAIN21_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN4_PG_STATUS), \ + SR(DOMAIN5_PG_STATUS), \ + SR(DOMAIN6_PG_STATUS), \ + SR(DOMAIN7_PG_STATUS), \ + SR(DOMAIN8_PG_STATUS), \ + SR(DOMAIN9_PG_STATUS), \ + SR(DOMAIN10_PG_STATUS), \ + SR(DOMAIN11_PG_STATUS), \ + SR(DOMAIN16_PG_STATUS), \ + SR(DOMAIN17_PG_STATUS), \ + SR(DOMAIN18_PG_STATUS), \ + SR(DOMAIN19_PG_STATUS), \ + SR(DOMAIN20_PG_STATUS), \ + SR(DOMAIN21_PG_STATUS), \ + SR(D1VGA_CONTROL), \ + SR(D2VGA_CONTROL), \ + SR(D3VGA_CONTROL), \ + SR(D4VGA_CONTROL), \ + SR(D5VGA_CONTROL), \ + SR(D6VGA_CONTROL), \ + SR(DC_IP_REQUEST_CNTL), \ + BL_REG_LIST() +#endif + struct dce_hwseq_registers { /* Backlight registers */ @@ -453,6 +517,69 @@ struct dce_hwseq_registers { HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_DIGON_OVRD, mask_sh), \ HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +#define HWSEQ_DCN2_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ + HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN8_PG_CONFIG, DOMAIN8_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN8_PG_CONFIG, DOMAIN8_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN9_PG_CONFIG, DOMAIN9_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN9_PG_CONFIG, DOMAIN9_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN10_PG_CONFIG, DOMAIN10_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN10_PG_CONFIG, DOMAIN10_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN11_PG_CONFIG, DOMAIN11_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN11_PG_CONFIG, DOMAIN11_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN16_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN16_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN17_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN17_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN18_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN18_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN19_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN19_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN20_PG_CONFIG, DOMAIN20_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN20_PG_CONFIG, DOMAIN20_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN21_PG_CONFIG, DOMAIN21_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN21_PG_CONFIG, DOMAIN21_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN1_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN2_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN3_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN4_PG_STATUS, DOMAIN4_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN8_PG_STATUS, DOMAIN8_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN9_PG_STATUS, DOMAIN9_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN10_PG_STATUS, DOMAIN10_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN11_PG_STATUS, DOMAIN11_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN16_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN17_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN18_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN19_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN20_PG_STATUS, DOMAIN20_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN21_PG_STATUS, DOMAIN21_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) +#endif + #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ type DCFEV_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c index cd26161bcc4d..a9061aaf1562 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c @@ -22,6 +22,9 @@ * Authors: AMD * */ + +#include <linux/delay.h> + #include "dce_i2c.h" #include "dce_i2c_hw.h" #include "reg_helper.h" @@ -149,6 +152,36 @@ static void process_channel_reply( } } +static bool is_engine_available(struct dce_i2c_hw *dce_i2c_hw) +{ + unsigned int arbitrate; + unsigned int i2c_hw_status; + + REG_GET(HW_STATUS, DC_I2C_DDC1_HW_STATUS, &i2c_hw_status); + if (i2c_hw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW) + return false; + + REG_GET(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, &arbitrate); + if (arbitrate == DC_I2C_REG_RW_CNTL_STATUS_DMCU_ONLY) + return false; + + return true; +} + +static bool is_hw_busy(struct dce_i2c_hw *dce_i2c_hw) +{ + uint32_t i2c_sw_status = 0; + + REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); + if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE) + return false; + + if (is_engine_available(dce_i2c_hw)) + return false; + + return true; +} + static bool process_transaction( struct dce_i2c_hw *dce_i2c_hw, struct i2c_request_transaction_data *request) @@ -159,6 +192,11 @@ static bool process_transaction( bool last_transaction = false; uint32_t value = 0; + if (is_hw_busy(dce_i2c_hw)) { + request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY; + return false; + } + last_transaction = ((dce_i2c_hw->transaction_count == 3) || (request->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) || (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ)); @@ -268,6 +306,14 @@ static bool setup_engine( struct dce_i2c_hw *dce_i2c_hw) { uint32_t i2c_setup_limit = I2C_SETUP_TIME_LIMIT_DCE; +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) + uint32_t reset_length = 0; +#endif + /* we have checked I2c not used by DMCU, set SW use I2C REQ to 1 to indicate SW using it*/ + REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, 1); + + /* we have checked I2c not used by DMCU, set SW use I2C REQ to 1 to indicate SW using it*/ + REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, 1); if (dce_i2c_hw->setup_limit != 0) i2c_setup_limit = dce_i2c_hw->setup_limit; @@ -286,33 +332,26 @@ static bool setup_engine( REG_UPDATE_N(SETUP, 2, FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), i2c_setup_limit, FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1); +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) + } else { + reset_length = dce_i2c_hw->send_reset_length; + REG_UPDATE_N(SETUP, 3, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), i2c_setup_limit, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_SEND_RESET_LENGTH), reset_length, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1); +#endif } /* Program HW priority * set to High - interrupt software I2C at any time * Enable restart of SW I2C that was interrupted by HW * disable queuing of software while I2C is in use by HW */ - REG_UPDATE_2(DC_I2C_ARBITRATION, - DC_I2C_NO_QUEUED_SW_GO, 0, - DC_I2C_SW_PRIORITY, DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL); + REG_UPDATE(DC_I2C_ARBITRATION, + DC_I2C_NO_QUEUED_SW_GO, 0); return true; } -static bool is_hw_busy(struct dce_i2c_hw *dce_i2c_hw) -{ - uint32_t i2c_sw_status = 0; - - REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); - if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE) - return false; - - reset_hw_engine(dce_i2c_hw); - - REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); - return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE; -} - static void release_engine( struct dce_i2c_hw *dce_i2c_hw) { @@ -322,8 +361,6 @@ static void release_engine( set_speed(dce_i2c_hw, dce_i2c_hw->original_speed); - /* Release I2C */ - REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, 1); /* Reset HW engine */ { @@ -343,19 +380,12 @@ static void release_engine( /* HW I2c engine - clock gating feature */ if (!dce_i2c_hw->engine_keep_power_up_count) REG_UPDATE_N(SETUP, 1, FN(SETUP, DC_I2C_DDC1_ENABLE), 0); + /* Release I2C after reset, so HW or DMCU could use it */ + REG_UPDATE_2(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, 1, + DC_I2C_SW_USE_I2C_REG_REQ, 0); } -static bool is_engine_available(struct dce_i2c_hw *dce_i2c_hw) -{ - unsigned int arbitrate; - - REG_GET(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, &arbitrate); - if (arbitrate == DC_I2C_REG_RW_CNTL_STATUS_DMCU_ONLY) - return false; - return true; -} - struct dce_i2c_hw *acquire_i2c_hw_engine( struct resource_pool *pool, struct ddc *ddc) @@ -453,6 +483,7 @@ static void submit_channel_request_hw( request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY; return; } + reset_hw_engine(dce_i2c_hw); execute_transaction(dce_i2c_hw); @@ -684,3 +715,23 @@ void dcn1_i2c_hw_construct( dce_i2c_hw->setup_limit = I2C_SETUP_TIME_LIMIT_DCN; } +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +void dcn2_i2c_hw_construct( + struct dce_i2c_hw *dce_i2c_hw, + struct dc_context *ctx, + uint32_t engine_id, + const struct dce_i2c_registers *regs, + const struct dce_i2c_shift *shifts, + const struct dce_i2c_mask *masks) +{ + dcn1_i2c_hw_construct(dce_i2c_hw, + ctx, + engine_id, + regs, + shifts, + masks); + dce_i2c_hw->send_reset_length = I2C_SEND_RESET_LENGTH_9; + if (ctx->dc->debug.scl_reset_length10) + dce_i2c_hw->send_reset_length = I2C_SEND_RESET_LENGTH_10; +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h index 575500755b2e..cb0234e5d597 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h @@ -84,6 +84,7 @@ enum { #define I2C_HW_ENGINE_COMMON_REG_LIST(id)\ SRI(SETUP, DC_I2C_DDC, id),\ SRI(SPEED, DC_I2C_DDC, id),\ + SRI(HW_STATUS, DC_I2C_DDC, id),\ SR(DC_I2C_ARBITRATION),\ SR(DC_I2C_CONTROL),\ SR(DC_I2C_SW_STATUS),\ @@ -105,6 +106,8 @@ enum { I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL, mask_sh),\ I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY, mask_sh),\ I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY, mask_sh),\ + I2C_SF(DC_I2C_DDC1_HW_STATUS, DC_I2C_DDC1_HW_STATUS, mask_sh),\ + I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, mask_sh),\ I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, mask_sh),\ I2C_SF(DC_I2C_ARBITRATION, DC_I2C_NO_QUEUED_SW_GO, mask_sh),\ I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_PRIORITY, mask_sh),\ @@ -145,7 +148,9 @@ struct dce_i2c_shift { uint8_t DC_I2C_DDC1_DATA_DRIVE_SEL; uint8_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY; uint8_t DC_I2C_DDC1_INTRA_BYTE_DELAY; + uint8_t DC_I2C_DDC1_HW_STATUS; uint8_t DC_I2C_SW_DONE_USING_I2C_REG; + uint8_t DC_I2C_SW_USE_I2C_REG_REQ; uint8_t DC_I2C_NO_QUEUED_SW_GO; uint8_t DC_I2C_SW_PRIORITY; uint8_t DC_I2C_SOFT_RESET; @@ -172,6 +177,9 @@ struct dce_i2c_shift { uint8_t DC_I2C_INDEX; uint8_t DC_I2C_INDEX_WRITE; uint8_t XTAL_REF_DIV; +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) + uint8_t DC_I2C_DDC1_SEND_RESET_LENGTH; +#endif uint8_t DC_I2C_REG_RW_CNTL_STATUS; }; @@ -183,7 +191,9 @@ struct dce_i2c_mask { uint32_t DC_I2C_DDC1_DATA_DRIVE_SEL; uint32_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY; uint32_t DC_I2C_DDC1_INTRA_BYTE_DELAY; + uint32_t DC_I2C_DDC1_HW_STATUS; uint32_t DC_I2C_SW_DONE_USING_I2C_REG; + uint32_t DC_I2C_SW_USE_I2C_REG_REQ; uint32_t DC_I2C_NO_QUEUED_SW_GO; uint32_t DC_I2C_SW_PRIORITY; uint32_t DC_I2C_SOFT_RESET; @@ -210,12 +220,22 @@ struct dce_i2c_mask { uint32_t DC_I2C_INDEX; uint32_t DC_I2C_INDEX_WRITE; uint32_t XTAL_REF_DIV; +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) + uint32_t DC_I2C_DDC1_SEND_RESET_LENGTH; +#endif uint32_t DC_I2C_REG_RW_CNTL_STATUS; }; +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +#define I2C_COMMON_MASK_SH_LIST_DCN2(mask_sh)\ + I2C_COMMON_MASK_SH_LIST_DCE110(mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_SEND_RESET_LENGTH, mask_sh) +#endif + struct dce_i2c_registers { uint32_t SETUP; uint32_t SPEED; + uint32_t HW_STATUS; uint32_t DC_I2C_ARBITRATION; uint32_t DC_I2C_CONTROL; uint32_t DC_I2C_SW_STATUS; @@ -292,6 +312,16 @@ void dcn1_i2c_hw_construct( const struct dce_i2c_shift *shifts, const struct dce_i2c_mask *masks); +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +void dcn2_i2c_hw_construct( + struct dce_i2c_hw *dce_i2c_hw, + struct dc_context *ctx, + uint32_t engine_id, + const struct dce_i2c_registers *regs, + const struct dce_i2c_shift *shifts, + const struct dce_i2c_mask *masks); +#endif + bool dce_i2c_submit_command_hw( struct resource_pool *pool, struct ddc *ddc, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c index f0266694cb56..a5a11c251e25 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c @@ -22,6 +22,9 @@ * Authors: AMD * */ + +#include <linux/delay.h> + #include "dce_i2c.h" #include "dce_i2c_sw.h" #include "include/gpio_service_interface.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c index 5d9506b3d46b..ce30dbf579d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -23,6 +23,8 @@ * */ +#include <linux/slab.h> + #include "dce_ipp.h" #include "reg_helper.h" #include "dm_services.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 314c04a915d2..8527cce81c6f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -23,6 +23,9 @@ * */ +#include <linux/delay.h> +#include <linux/slab.h> + #include "reg_helper.h" #include "core_types.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 87093894ea9e..51081d9ae3fb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -23,6 +23,8 @@ * */ +#include <linux/slab.h> + #include "dm_services.h" #include "basics/conversion.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 14309fe6f2e6..5e2b4d47c548 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -23,6 +23,8 @@ * */ +#include <linux/delay.h> + #include "dc_bios_types.h" #include "dce_stream_encoder.h" #include "reg_helper.h" @@ -418,6 +420,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( break; case COLOR_SPACE_YCBCR709: case COLOR_SPACE_YCBCR709_LIMITED: + case COLOR_SPACE_YCBCR709_BLACK: misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */ misc1 = misc1 & ~0x80; /* bit7 = 0*/ dynamic_range_ycbcr = 1; /*bt709*/ @@ -1123,19 +1126,6 @@ union audio_cea_channels { } channels; }; -struct audio_clock_info { - /* pixel clock frequency*/ - uint32_t pixel_clock_in_10khz; - /* N - 32KHz audio */ - uint32_t n_32khz; - /* CTS - 32KHz audio*/ - uint32_t cts_32khz; - uint32_t n_44khz; - uint32_t cts_44khz; - uint32_t n_48khz; - uint32_t cts_48khz; -}; - /* 25.2MHz/1.001*/ /* 25.2MHz/1.001*/ /* 25.2MHz*/ |