Skip to content

Commit 4c4cc7a

Browse files
mkaholaRadhakrishna Sripada
authored andcommitted
drm/i915/mtl: Add support for PM DEMAND
MTL introduces a new way to instruct the PUnit with power and bandwidth requirements of DE. Add the functionality to program the registers and handle waits using interrupts. The current wait time for timeouts is programmed for 10 msecs to factor in the worst case scenarios. Changes made to use REG_BIT for a register that we touched(GEN8_DE_MISC_IER _MMIO). Wa_14016740474 is added which applies to Xe_LPD+ display v2: checkpatch warning fixes, simplify program pmdemand part v3: update to dbufs and pipes values to pmdemand register(stan) Removed the macro usage in update_pmdemand_values() v4: move the pmdemand_pre_plane_update before cdclk update pmdemand_needs_update included cdclk params comparisons pmdemand_state NULL check (Gustavo) pmdemand.o in sorted order in the makefile (Jani) update pmdemand misc irq handler loop (Gustavo) active phys bitmask and programming correction (Gustavo) v5: simplify pmdemand_state structure simplify methods to find active phys and max port clock Timeout in case of previou pmdemand task pending (Gustavo) v6: rebasing updates to max_ddiclk calculations (Gustavo) updates to active_phys count method (Gustavo) v7: use two separate loop to iterate throug old and new crtc states to calculate the active phys (Gustavo) v8: use uniform function names (Gustavo) v9: For phys change iterate through connectors (Imre) Look for change in phys for pmdemand update (Gustavo, Imre) Some more stlying changes (Imre) Update pmdemand state during HW readout/sanitize (Imre) v10: Fix CI checkpatch warnings v11: use correct pmdemand object pointer during hw readout, simplify the check for phys need update (Gustavo) v12: Handle possible non serialize cases (Imre) Initialise also pmdemand params HW readout (Imre) Update active phys mask during sanitize calls (Imre) Check TC/encoder changes to limit connector update (Imre) v13: Check display version before accessing pmdemand functions v14: Move is_serialized to intel_global_state.c simplify update params and other stlying issues (Imre) Bspec: 66451, 64636, 64602, 64603 Cc: Matt Atwood <matthew.s.atwood@intel.com> Cc: Matt Roper <matthew.d.roper@intel.com> Cc: Lucas De Marchi <lucas.demarchi@intel.com> Cc: Gustavo Sousa <gustavo.sousa@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com> Signed-off-by: Mika Kahola <mika.kahola@intel.com> Signed-off-by: Vinod Govindapillai <vinod.govindapillai@intel.com> Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com> #v4 Acked-by: Gustavo Sousa <gustavo.sousa@intel.com> #v11 Reviewed-by: Imre Deak <imre.deak@intel.com> [RK: Fixed minor typo in one of the comments. s/qclck_gc/qclk_gv/] Signed-off-by: Radhakrishna Sripada <radhakrishna.sripada@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230606201032.347449-1-vinod.govindapillai@intel.com
1 parent a5819e5 commit 4c4cc7a

12 files changed

Lines changed: 821 additions & 6 deletions

drivers/gpu/drm/i915/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ i915-y += \
269269
display/intel_pch_display.o \
270270
display/intel_pch_refclk.o \
271271
display/intel_plane_initial.o \
272+
display/intel_pmdemand.o \
272273
display/intel_psr.o \
273274
display/intel_quirks.o \
274275
display/intel_sprite.o \

drivers/gpu/drm/i915/display/intel_display.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
#include "intel_pcode.h"
100100
#include "intel_pipe_crc.h"
101101
#include "intel_plane_initial.h"
102+
#include "intel_pmdemand.h"
102103
#include "intel_pps.h"
103104
#include "intel_psr.h"
104105
#include "intel_sdvo.h"
@@ -6354,6 +6355,10 @@ int intel_atomic_check(struct drm_device *dev,
63546355
return ret;
63556356
}
63566357

6358+
ret = intel_pmdemand_atomic_check(state);
6359+
if (ret)
6360+
goto fail;
6361+
63576362
ret = intel_atomic_check_crtcs(state);
63586363
if (ret)
63596364
goto fail;
@@ -6999,6 +7004,14 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
69997004
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
70007005
crtc->config = new_crtc_state;
70017006

7007+
/*
7008+
* In XE_LPD+ Pmdemand combines many parameters such as voltage index,
7009+
* plls, cdclk frequency, QGV point selection parameter etc. Voltage
7010+
* index, cdclk/ddiclk frequencies are supposed to be configured before
7011+
* the cdclk config is set.
7012+
*/
7013+
intel_pmdemand_pre_plane_update(state);
7014+
70027015
if (state->modeset) {
70037016
drm_atomic_helper_update_legacy_modeset_state(dev, &state->base);
70047017

@@ -7118,6 +7131,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
71187131
intel_verify_planes(state);
71197132

71207133
intel_sagv_post_plane_update(state);
7134+
intel_pmdemand_post_plane_update(state);
71217135

71227136
drm_atomic_helper_commit_hw_done(&state->base);
71237137

drivers/gpu/drm/i915/display/intel_display_core.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,15 @@ struct intel_display {
345345
struct intel_global_obj obj;
346346
} dbuf;
347347

348+
struct {
349+
wait_queue_head_t waitqueue;
350+
351+
/* mutex to protect pmdemand programming sequence */
352+
struct mutex lock;
353+
354+
struct intel_global_obj obj;
355+
} pmdemand;
356+
348357
struct {
349358
/*
350359
* dkl.phy_lock protects against concurrent access of the

drivers/gpu/drm/i915/display/intel_display_driver.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "intel_opregion.h"
4848
#include "intel_overlay.h"
4949
#include "intel_plane_initial.h"
50+
#include "intel_pmdemand.h"
5051
#include "intel_pps.h"
5152
#include "intel_quirks.h"
5253
#include "intel_vga.h"
@@ -211,6 +212,8 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
211212
if (ret < 0)
212213
goto cleanup_vga;
213214

215+
intel_pmdemand_init_early(i915);
216+
214217
intel_power_domains_init_hw(i915, false);
215218

216219
if (!HAS_DISPLAY(i915))
@@ -240,6 +243,10 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
240243
if (ret)
241244
goto cleanup_vga_client_pw_domain_dmc;
242245

246+
ret = intel_pmdemand_init(i915);
247+
if (ret)
248+
goto cleanup_vga_client_pw_domain_dmc;
249+
243250
init_llist_head(&i915->display.atomic_helper.free_list);
244251
INIT_WORK(&i915->display.atomic_helper.free_work,
245252
intel_atomic_helper_free_state_worker);

drivers/gpu/drm/i915/display/intel_display_irq.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "intel_fifo_underrun.h"
1919
#include "intel_gmbus.h"
2020
#include "intel_hotplug_irq.h"
21+
#include "intel_pmdemand.h"
2122
#include "intel_psr.h"
2223
#include "intel_psr_regs.h"
2324

@@ -827,12 +828,27 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
827828
return GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
828829
}
829830

831+
static void intel_pmdemand_irq_handler(struct drm_i915_private *dev_priv)
832+
{
833+
wake_up_all(&dev_priv->display.pmdemand.waitqueue);
834+
}
835+
830836
static void
831837
gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
832838
{
833839
bool found = false;
834840

835-
if (iir & GEN8_DE_MISC_GSE) {
841+
if (DISPLAY_VER(dev_priv) >= 14) {
842+
if (iir & (XELPDP_PMDEMAND_RSP |
843+
XELPDP_PMDEMAND_RSPTOUT_ERR)) {
844+
if (iir & XELPDP_PMDEMAND_RSPTOUT_ERR)
845+
drm_dbg(&dev_priv->drm,
846+
"Error waiting for Punit PM Demand Response\n");
847+
848+
intel_pmdemand_irq_handler(dev_priv);
849+
found = true;
850+
}
851+
} else if (iir & GEN8_DE_MISC_GSE) {
836852
intel_opregion_asle_intr(dev_priv);
837853
found = true;
838854
}
@@ -1576,7 +1592,10 @@ void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
15761592
if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
15771593
de_port_masked |= BXT_DE_PORT_GMBUS;
15781594

1579-
if (DISPLAY_VER(dev_priv) >= 11) {
1595+
if (DISPLAY_VER(dev_priv) >= 14) {
1596+
de_misc_masked |= XELPDP_PMDEMAND_RSPTOUT_ERR |
1597+
XELPDP_PMDEMAND_RSP;
1598+
} else if (DISPLAY_VER(dev_priv) >= 11) {
15801599
enum port port;
15811600

15821601
if (intel_bios_is_dsi_present(dev_priv, &port))

drivers/gpu/drm/i915/display/intel_display_power.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "intel_mchbar_regs.h"
2121
#include "intel_pch_refclk.h"
2222
#include "intel_pcode.h"
23+
#include "intel_pmdemand.h"
2324
#include "intel_pps_regs.h"
2425
#include "intel_snps_phy.h"
2526
#include "skl_watermark.h"
@@ -1082,20 +1083,29 @@ void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv,
10821083

10831084
static void gen9_dbuf_enable(struct drm_i915_private *dev_priv)
10841085
{
1086+
u8 slices_mask;
1087+
10851088
dev_priv->display.dbuf.enabled_slices =
10861089
intel_enabled_dbuf_slices_mask(dev_priv);
10871090

1091+
slices_mask = BIT(DBUF_S1) | dev_priv->display.dbuf.enabled_slices;
1092+
1093+
if (DISPLAY_VER(dev_priv) >= 14)
1094+
intel_pmdemand_program_dbuf(dev_priv, slices_mask);
1095+
10881096
/*
10891097
* Just power up at least 1 slice, we will
10901098
* figure out later which slices we have and what we need.
10911099
*/
1092-
gen9_dbuf_slices_update(dev_priv, BIT(DBUF_S1) |
1093-
dev_priv->display.dbuf.enabled_slices);
1100+
gen9_dbuf_slices_update(dev_priv, slices_mask);
10941101
}
10951102

10961103
static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)
10971104
{
10981105
gen9_dbuf_slices_update(dev_priv, 0);
1106+
1107+
if (DISPLAY_VER(dev_priv) >= 14)
1108+
intel_pmdemand_program_dbuf(dev_priv, 0);
10991109
}
11001110

11011111
static void gen12_dbuf_slices_config(struct drm_i915_private *dev_priv)

drivers/gpu/drm/i915/display/intel_global_state.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,15 @@ int intel_atomic_serialize_global_state(struct intel_global_state *obj_state)
255255

256256
return 0;
257257
}
258+
259+
bool
260+
intel_atomic_global_state_is_serialized(struct intel_atomic_state *state)
261+
{
262+
struct drm_i915_private *i915 = to_i915(state->base.dev);
263+
struct intel_crtc *crtc;
264+
265+
for_each_intel_crtc(&i915->drm, crtc)
266+
if (!intel_atomic_get_new_crtc_state(state, crtc))
267+
return false;
268+
return true;
269+
}

drivers/gpu/drm/i915/display/intel_global_state.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,6 @@ void intel_atomic_clear_global_state(struct intel_atomic_state *state);
8787
int intel_atomic_lock_global_state(struct intel_global_state *obj_state);
8888
int intel_atomic_serialize_global_state(struct intel_global_state *obj_state);
8989

90+
bool intel_atomic_global_state_is_serialized(struct intel_atomic_state *state);
91+
9092
#endif

drivers/gpu/drm/i915/display/intel_modeset_setup.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "intel_fifo_underrun.h"
2727
#include "intel_modeset_setup.h"
2828
#include "intel_pch_display.h"
29+
#include "intel_pmdemand.h"
2930
#include "intel_tc.h"
3031
#include "intel_vblank.h"
3132
#include "intel_wm.h"
@@ -115,6 +116,8 @@ static void set_encoder_for_connector(struct intel_connector *connector,
115116
static void reset_encoder_connector_state(struct intel_encoder *encoder)
116117
{
117118
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
119+
struct intel_pmdemand_state *pmdemand_state =
120+
to_intel_pmdemand_state(i915->display.pmdemand.obj.state);
118121
struct intel_connector *connector;
119122
struct drm_connector_list_iter conn_iter;
120123

@@ -123,6 +126,10 @@ static void reset_encoder_connector_state(struct intel_encoder *encoder)
123126
if (connector->base.encoder != &encoder->base)
124127
continue;
125128

129+
/* Clear the corresponding bit in pmdemand active phys mask */
130+
intel_pmdemand_update_phys_mask(i915, encoder,
131+
pmdemand_state, false);
132+
126133
set_encoder_for_connector(connector, NULL);
127134

128135
connector->base.dpms = DRM_MODE_DPMS_OFF;
@@ -151,6 +158,8 @@ static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc)
151158
to_intel_cdclk_state(i915->display.cdclk.obj.state);
152159
struct intel_dbuf_state *dbuf_state =
153160
to_intel_dbuf_state(i915->display.dbuf.obj.state);
161+
struct intel_pmdemand_state *pmdemand_state =
162+
to_intel_pmdemand_state(i915->display.pmdemand.obj.state);
154163
struct intel_crtc_state *crtc_state =
155164
to_intel_crtc_state(crtc->base.state);
156165
enum pipe pipe = crtc->pipe;
@@ -174,6 +183,8 @@ static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc)
174183

175184
bw_state->data_rate[pipe] = 0;
176185
bw_state->num_active_planes[pipe] = 0;
186+
187+
intel_pmdemand_update_port_clock(i915, pmdemand_state, pipe, 0);
177188
}
178189

179190
/*
@@ -552,6 +563,8 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
552563
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
553564
struct intel_crtc_state *crtc_state = crtc ?
554565
to_intel_crtc_state(crtc->base.state) : NULL;
566+
struct intel_pmdemand_state *pmdemand_state =
567+
to_intel_pmdemand_state(i915->display.pmdemand.obj.state);
555568

556569
/*
557570
* We need to check both for a crtc link (meaning that the encoder is
@@ -575,6 +588,10 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
575588
encoder->base.base.id,
576589
encoder->base.name);
577590

591+
/* Clear the corresponding bit in pmdemand active phys mask */
592+
intel_pmdemand_update_phys_mask(i915, encoder,
593+
pmdemand_state, false);
594+
578595
/*
579596
* Connector is active, but has no active pipe. This is fallout
580597
* from our resume register restoring. Disable the encoder
@@ -661,6 +678,8 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
661678
to_intel_cdclk_state(i915->display.cdclk.obj.state);
662679
struct intel_dbuf_state *dbuf_state =
663680
to_intel_dbuf_state(i915->display.dbuf.obj.state);
681+
struct intel_pmdemand_state *pmdemand_state =
682+
to_intel_pmdemand_state(i915->display.pmdemand.obj.state);
664683
enum pipe pipe;
665684
struct intel_crtc *crtc;
666685
struct intel_encoder *encoder;
@@ -724,7 +743,15 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
724743
intel_encoder_get_config(encoder, slave_crtc_state);
725744
}
726745
}
746+
747+
intel_pmdemand_update_phys_mask(i915, encoder,
748+
pmdemand_state,
749+
true);
727750
} else {
751+
intel_pmdemand_update_phys_mask(i915, encoder,
752+
pmdemand_state,
753+
false);
754+
728755
encoder->base.crtc = NULL;
729756
}
730757

@@ -841,8 +868,13 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
841868
cdclk_state->min_voltage_level[crtc->pipe] =
842869
crtc_state->min_voltage_level;
843870

871+
intel_pmdemand_update_port_clock(i915, pmdemand_state, pipe,
872+
crtc_state->port_clock);
873+
844874
intel_bw_crtc_update(bw_state, crtc_state);
845875
}
876+
877+
intel_pmdemand_init_pmdemand_params(i915, pmdemand_state);
846878
}
847879

848880
static void

0 commit comments

Comments
 (0)