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: Read PHY_VDR_0_CONFIG register

Read PHY_VDR_0_CONFIG to check if there is any change in the register and
decide based on that if P2P sequence to change the data rate of LT PHY
are required or not. This scenario only happens if the requested mode
uses 1.62Gbps with DP mode since LT PHY defaults to this mode if
any other mode is requested we need to follow the whole sequence.

Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
Reviewed-by: Arun R Murthy <arun.r.murthy@intel.com>
Link: https://patch.msgid.link/20251101032513.4171255-8-suraj.kandpal@intel.com

+123 -25
+1 -2
drivers/gpu/drm/i915/display/intel_cx0_phy.c
··· 271 271 return 0; 272 272 } 273 273 274 - static u8 intel_cx0_read(struct intel_encoder *encoder, 275 - u8 lane_mask, u16 addr) 274 + u8 intel_cx0_read(struct intel_encoder *encoder, u8 lane_mask, u16 addr) 276 275 { 277 276 int lane = lane_mask_to_lane(lane_mask); 278 277
+1
drivers/gpu/drm/i915/display/intel_cx0_phy.h
··· 46 46 int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock); 47 47 void intel_cx0_setup_powerdown(struct intel_encoder *encoder); 48 48 bool intel_cx0_is_hdmi_frl(u32 clock); 49 + u8 intel_cx0_read(struct intel_encoder *encoder, u8 lane_mask, u16 addr); 49 50 int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder); 50 51 void intel_cx0_pll_power_save_wa(struct intel_display *display); 51 52 void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder,
+121 -23
drivers/gpu/drm/i915/display/intel_lt_phy.c
··· 6 6 #include <drm/drm_print.h> 7 7 8 8 #include "i915_reg.h" 9 + #include "i915_utils.h" 9 10 #include "intel_cx0_phy.h" 10 11 #include "intel_cx0_phy_regs.h" 11 12 #include "intel_de.h" ··· 15 14 #include "intel_hdmi.h" 16 15 #include "intel_lt_phy.h" 17 16 #include "intel_lt_phy_regs.h" 17 + #include "intel_psr.h" 18 18 #include "intel_tc.h" 19 19 20 20 #define INTEL_LT_PHY_LANE0 BIT(0) 21 21 #define INTEL_LT_PHY_LANE1 BIT(1) 22 22 #define INTEL_LT_PHY_BOTH_LANES (INTEL_LT_PHY_LANE1 |\ 23 23 INTEL_LT_PHY_LANE0) 24 + #define MODE_DP 3 24 25 25 26 static u8 intel_lt_phy_get_owned_lane_mask(struct intel_encoder *encoder) 26 27 { ··· 33 30 34 31 return intel_tc_port_max_lane_count(dig_port) > 2 35 32 ? INTEL_LT_PHY_BOTH_LANES : INTEL_LT_PHY_LANE0; 33 + } 34 + 35 + static u8 intel_lt_phy_read(struct intel_encoder *encoder, u8 lane_mask, u16 addr) 36 + { 37 + return intel_cx0_read(encoder, lane_mask, addr); 36 38 } 37 39 38 40 static void ··· 157 149 XELPDP_SSC_ENABLE_PLLB, val); 158 150 } 159 151 152 + static u32 intel_lt_phy_get_dp_clock(u8 rate) 153 + { 154 + switch (rate) { 155 + case 0: 156 + return 162000; 157 + case 1: 158 + return 270000; 159 + case 2: 160 + return 540000; 161 + case 3: 162 + return 810000; 163 + case 4: 164 + return 216000; 165 + case 5: 166 + return 243000; 167 + case 6: 168 + return 324000; 169 + case 7: 170 + return 432000; 171 + case 8: 172 + return 1000000; 173 + case 9: 174 + return 1350000; 175 + case 10: 176 + return 2000000; 177 + case 11: 178 + return 675000; 179 + default: 180 + MISSING_CASE(rate); 181 + return 0; 182 + } 183 + } 184 + 185 + static bool 186 + intel_lt_phy_config_changed(struct intel_encoder *encoder, 187 + const struct intel_crtc_state *crtc_state) 188 + { 189 + u8 val, rate; 190 + u32 clock; 191 + 192 + val = intel_lt_phy_read(encoder, INTEL_LT_PHY_LANE0, 193 + LT_PHY_VDR_0_CONFIG); 194 + rate = REG_FIELD_GET8(LT_PHY_VDR_RATE_ENCODING_MASK, val); 195 + 196 + /* 197 + * The only time we do not reconfigure the PLL is when we are 198 + * using 1.62 Gbps clock since PHY PLL defaults to that 199 + * otherwise we always need to reconfigure it. 200 + */ 201 + if (intel_crtc_has_dp_encoder(crtc_state)) { 202 + clock = intel_lt_phy_get_dp_clock(rate); 203 + if (crtc_state->port_clock == 1620000 && crtc_state->port_clock == clock) 204 + return false; 205 + } 206 + 207 + return true; 208 + } 209 + 210 + static intel_wakeref_t intel_lt_phy_transaction_begin(struct intel_encoder *encoder) 211 + { 212 + struct intel_display *display = to_intel_display(encoder); 213 + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 214 + intel_wakeref_t wakeref; 215 + 216 + intel_psr_pause(intel_dp); 217 + wakeref = intel_display_power_get(display, POWER_DOMAIN_DC_OFF); 218 + 219 + return wakeref; 220 + } 221 + 222 + static void intel_lt_phy_transaction_end(struct intel_encoder *encoder, intel_wakeref_t wakeref) 223 + { 224 + struct intel_display *display = to_intel_display(encoder); 225 + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 226 + 227 + intel_psr_resume(intel_dp); 228 + intel_display_power_put(display, POWER_DOMAIN_DC_OFF, wakeref); 229 + } 230 + 160 231 void intel_lt_phy_pll_enable(struct intel_encoder *encoder, 161 232 const struct intel_crtc_state *crtc_state) 162 233 { 234 + struct intel_display *display = to_intel_display(encoder); 163 235 struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 164 236 bool lane_reversal = dig_port->lane_reversal; 165 237 u8 owned_lane_mask = intel_lt_phy_get_owned_lane_mask(encoder); 238 + intel_wakeref_t wakeref = 0; 239 + 240 + wakeref = intel_lt_phy_transaction_begin(encoder); 166 241 167 242 /* 1. Enable MacCLK at default 162 MHz frequency. */ 168 243 intel_lt_phy_lane_reset(encoder, crtc_state->lane_count); ··· 261 170 * 4. Read the PHY message bus VDR register PHY_VDR_0_Config check enabled PLL type, 262 171 * encoded rate and encoded mode. 263 172 */ 264 - /* 265 - * 5. Program the PHY internal PLL registers over PHY message bus for the desired 266 - * frequency and protocol type 267 - */ 268 - /* 6. Use the P2P transaction flow */ 269 - /* 270 - * 6.1. Set the PHY VDR register 0xCC4[Rate Control VDR Update] = 1 over PHY message 271 - * bus for Owned PHY Lanes. 272 - */ 273 - /* 274 - * 6.2. Poll for P2P Transaction Ready = "1" and read the MAC message bus VDR register 275 - * at offset 0xC00 for Owned PHY Lanes. 276 - */ 277 - /* 6.3. Clear P2P transaction Ready bit. */ 278 - /* 7. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 0. */ 279 - /* 8. Poll for PORT_CLOCK_CTL[PCLK PLL Ack LN0]= 0. */ 280 - /* 281 - * 9. Follow the Display Voltage Frequency Switching - Sequence Before Frequency Change. 282 - * We handle this step in bxt_set_cdclk() 283 - */ 284 - /* 10. Program DDI_CLK_VALFREQ to match intended DDI clock frequency. */ 285 - /* 11. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 1. */ 286 - /* 12. Poll for PORT_CLOCK_CTL[PCLK PLL Ack LN0]= 1. */ 173 + if (intel_lt_phy_config_changed(encoder, crtc_state)) { 174 + /* 175 + * 5. Program the PHY internal PLL registers over PHY message bus for the desired 176 + * frequency and protocol type 177 + */ 178 + /* 6. Use the P2P transaction flow */ 179 + /* 180 + * 6.1. Set the PHY VDR register 0xCC4[Rate Control VDR Update] = 1 over PHY message 181 + * bus for Owned PHY Lanes. 182 + */ 183 + /* 184 + * 6.2. Poll for P2P Transaction Ready = "1" and read the MAC message bus VDR 185 + * register at offset 0xC00 for Owned PHY Lanes*. 186 + */ 187 + /* 6.3. Clear P2P transaction Ready bit. */ 188 + /* 7. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 0. */ 189 + /* 8. Poll for PORT_CLOCK_CTL[PCLK PLL Ack LN0]= 0. */ 190 + /* 191 + * 9. Follow the Display Voltage Frequency Switching - Sequence Before Frequency 192 + * Change. We handle this step in bxt_set_cdclk(). 193 + */ 194 + /* 10. Program DDI_CLK_VALFREQ to match intended DDI clock frequency. */ 195 + /* 11. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 1. */ 196 + /* 12. Poll for PORT_CLOCK_CTL[PCLK PLL Ack LN0]= 1. */ 197 + } else { 198 + intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), crtc_state->port_clock); 199 + } 200 + 287 201 /* 13. Ungate the forward clock by setting PORT_CLOCK_CTL[Forward Clock Ungate] = 1. */ 288 202 /* 14. SW clears PORT_BUF_CTL2 [PHY Pulse Status]. */ 289 203 /* ··· 302 206 * We handle this step in bxt_set_cdclk() 303 207 */ 304 208 /* 19. Move the PHY powerdown state to Active and program to enable/disable transmitters */ 209 + 210 + intel_lt_phy_transaction_end(encoder, wakeref); 305 211 }