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

Configure Feed

Select the types of activity you want to include in your feed.

drm/i915/ltphy: Add function to calculate LT PHY port clock

Create a reverse algorithm which is used to find port clock
from the LT PHY state is provided which is used for
comparision & verification functions.

Bspec: 74667
Signed-off-by: Nemesa Garg <nemesa.garg@intel.com>
Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
Reviewed-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Link: https://patch.msgid.link/20251101032513.4171255-13-suraj.kandpal@intel.com

+97
+2
drivers/gpu/drm/i915/display/intel_dpll.c
··· 1247 1247 return ret; 1248 1248 1249 1249 /* TODO: Do the readback via intel_compute_shared_dplls() */ 1250 + crtc_state->port_clock = 1251 + intel_lt_phy_calc_port_clock(encoder, crtc_state); 1250 1252 1251 1253 crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state); 1252 1254
+92
drivers/gpu/drm/i915/display/intel_lt_phy.c
··· 1235 1235 return false; 1236 1236 } 1237 1237 1238 + static int 1239 + intel_lt_phy_calc_hdmi_port_clock(const struct intel_lt_phy_pll_state *lt_state) 1240 + { 1241 + #define REF_CLK_KHZ 38400 1242 + #define REGVAL(i) ( \ 1243 + (lt_state->data[i][3]) | \ 1244 + (lt_state->data[i][2] << 8) | \ 1245 + (lt_state->data[i][1] << 16) | \ 1246 + (lt_state->data[i][0] << 24) \ 1247 + ) 1248 + 1249 + int clk = 0; 1250 + u32 d8, pll_reg_5, pll_reg_3, pll_reg_57, m2div_frac, m2div_int; 1251 + u64 temp0, temp1; 1252 + /* 1253 + * The algorithm uses '+' to combine bitfields when 1254 + * constructing PLL_reg3 and PLL_reg57: 1255 + * PLL_reg57 = (D7 << 24) + (postdiv << 15) + (D8 << 7) + D6_new; 1256 + * PLL_reg3 = (D4 << 21) + (D3 << 18) + (D1 << 15) + (m2div_int << 5); 1257 + * 1258 + * However, this is likely intended to be a bitwise OR operation, 1259 + * as each field occupies distinct, non-overlapping bits in the register. 1260 + * 1261 + * PLL_reg57 is composed of following fields packed into a 32-bit value: 1262 + * - D7: max value 10 -> fits in 4 bits -> placed at bits 24-27 1263 + * - postdiv: max value 9 -> fits in 4 bits -> placed at bits 15-18 1264 + * - D8: derived from loop_cnt / 2, max 127 -> fits in 7 bits 1265 + * (though 8 bits are given to it) -> placed at bits 7-14 1266 + * - D6_new: fits in lower 7 bits -> placed at bits 0-6 1267 + * PLL_reg57 = (D7 << 24) | (postdiv << 15) | (D8 << 7) | D6_new; 1268 + * 1269 + * Similarly, PLL_reg3 is packed as: 1270 + * - D4: max value 256 -> fits in 9 bits -> placed at bits 21-29 1271 + * - D3: max value 9 -> fits in 4 bits -> placed at bits 18-21 1272 + * - D1: max value 2 -> fits in 2 bits -> placed at bits 15-16 1273 + * - m2div_int: max value 511 -> fits in 9 bits (10 bits allocated) 1274 + * -> placed at bits 5-14 1275 + * PLL_reg3 = (D4 << 21) | (D3 << 18) | (D1 << 15) | (m2div_int << 5); 1276 + */ 1277 + pll_reg_5 = REGVAL(2); 1278 + pll_reg_3 = REGVAL(1); 1279 + pll_reg_57 = REGVAL(3); 1280 + m2div_frac = pll_reg_5; 1281 + 1282 + /* 1283 + * From forward algorithm we know 1284 + * m2div = 2 * m2 1285 + * val = y * frequency * 5 1286 + * So now, 1287 + * frequency = (m2 * 2 * refclk_khz / (d8 * 10)) 1288 + * frequency = (m2div * refclk_khz / (d8 * 10)) 1289 + */ 1290 + d8 = (pll_reg_57 & REG_GENMASK(14, 7)) >> 7; 1291 + m2div_int = (pll_reg_3 & REG_GENMASK(14, 5)) >> 5; 1292 + temp0 = ((u64)m2div_frac * REF_CLK_KHZ) >> 32; 1293 + temp1 = (u64)m2div_int * REF_CLK_KHZ; 1294 + if (d8 == 0) 1295 + return 0; 1296 + 1297 + clk = div_u64((temp1 + temp0), d8 * 10); 1298 + 1299 + return clk; 1300 + } 1301 + 1302 + int 1303 + intel_lt_phy_calc_port_clock(struct intel_encoder *encoder, 1304 + const struct intel_crtc_state *crtc_state) 1305 + { 1306 + int clk; 1307 + const struct intel_lt_phy_pll_state *lt_state = 1308 + &crtc_state->dpll_hw_state.ltpll; 1309 + u8 mode, rate; 1310 + 1311 + mode = REG_FIELD_GET8(LT_PHY_VDR_MODE_ENCODING_MASK, 1312 + lt_state->config[0]); 1313 + /* 1314 + * For edp/dp read the clock value from the tables 1315 + * and return the clock as the algorithm used for 1316 + * calculating the port clock does not exactly matches 1317 + * with edp/dp clock. 1318 + */ 1319 + if (mode == MODE_DP) { 1320 + rate = REG_FIELD_GET8(LT_PHY_VDR_RATE_ENCODING_MASK, 1321 + lt_state->config[0]); 1322 + clk = intel_lt_phy_get_dp_clock(rate); 1323 + } else { 1324 + clk = intel_lt_phy_calc_hdmi_port_clock(lt_state); 1325 + } 1326 + 1327 + return clk; 1328 + } 1329 + 1238 1330 int 1239 1331 intel_lt_phy_pll_calc_state(struct intel_crtc_state *crtc_state, 1240 1332 struct intel_encoder *encoder)
+3
drivers/gpu/drm/i915/display/intel_lt_phy.h
··· 10 10 11 11 struct intel_encoder; 12 12 struct intel_crtc_state; 13 + struct intel_lt_phy_pll_state; 13 14 14 15 void intel_lt_phy_pll_enable(struct intel_encoder *encoder, 15 16 const struct intel_crtc_state *crtc_state); 16 17 int 17 18 intel_lt_phy_pll_calc_state(struct intel_crtc_state *crtc_state, 18 19 struct intel_encoder *encoder); 20 + int intel_lt_phy_calc_port_clock(struct intel_encoder *encoder, 21 + const struct intel_crtc_state *crtc_state); 19 22 20 23 #define HAS_LT_PHY(display) (DISPLAY_VER(display) >= 35) 21 24