Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: get refclk from MICROSECOND_TIME_BASE_DIV HW register

[why]
recent VBIOS dce_infotable reference clock change caused a I2c regression.
instead of relying on vbios, let's get it from HW directly.

Signed-off-by: Charlene Liu <Charlene.Liu@amd.com>
Reviewed-by: Chris Park <Chris.Park@amd.com>
Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Charlene Liu and committed by
Alex Deucher
452c76df 1a365683

+13 -3
+10 -3
drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
··· 264 264 struct dce_i2c_hw *dce_i2c_hw, 265 265 uint32_t speed) 266 266 { 267 - uint32_t xtal_ref_div = 0; 267 + uint32_t xtal_ref_div = 0, ref_base_div = 0; 268 268 uint32_t prescale = 0; 269 + uint32_t i2c_ref_clock = 0; 269 270 270 271 if (speed == 0) 271 272 return; 272 273 273 - REG_GET(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, &xtal_ref_div); 274 + REG_GET_2(MICROSECOND_TIME_BASE_DIV, MICROSECOND_TIME_BASE_DIV, &ref_base_div, 275 + XTAL_REF_DIV, &xtal_ref_div); 274 276 275 277 if (xtal_ref_div == 0) 276 278 xtal_ref_div = 2; 277 279 278 - prescale = ((dce_i2c_hw->reference_frequency * 2) / xtal_ref_div) / speed; 280 + if (ref_base_div == 0) 281 + i2c_ref_clock = (dce_i2c_hw->reference_frequency * 2); 282 + else 283 + i2c_ref_clock = ref_base_div * 1000; 284 + 285 + prescale = (i2c_ref_clock / xtal_ref_div) / speed; 279 286 280 287 if (dce_i2c_hw->masks->DC_I2C_DDC1_START_STOP_TIMING_CNTL) 281 288 REG_UPDATE_N(SPEED, 3,
+3
drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h
··· 139 139 I2C_SF(DC_I2C_DATA, DC_I2C_INDEX, mask_sh),\ 140 140 I2C_SF(DC_I2C_DATA, DC_I2C_INDEX_WRITE, mask_sh),\ 141 141 I2C_SF(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, mask_sh),\ 142 + I2C_SF(MICROSECOND_TIME_BASE_DIV, MICROSECOND_TIME_BASE_DIV, mask_sh),\ 142 143 I2C_SF(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, mask_sh) 143 144 144 145 #define I2C_COMMON_MASK_SH_LIST_DCE110(mask_sh)\ ··· 183 182 uint8_t DC_I2C_INDEX; 184 183 uint8_t DC_I2C_INDEX_WRITE; 185 184 uint8_t XTAL_REF_DIV; 185 + uint8_t MICROSECOND_TIME_BASE_DIV; 186 186 uint8_t DC_I2C_DDC1_SEND_RESET_LENGTH; 187 187 uint8_t DC_I2C_REG_RW_CNTL_STATUS; 188 188 uint8_t I2C_LIGHT_SLEEP_FORCE; ··· 227 225 uint32_t DC_I2C_INDEX; 228 226 uint32_t DC_I2C_INDEX_WRITE; 229 227 uint32_t XTAL_REF_DIV; 228 + uint32_t MICROSECOND_TIME_BASE_DIV; 230 229 uint32_t DC_I2C_DDC1_SEND_RESET_LENGTH; 231 230 uint32_t DC_I2C_REG_RW_CNTL_STATUS; 232 231 uint32_t I2C_LIGHT_SLEEP_FORCE;